Oi Falaremos sobre teclas de atalho no WEBAPI + JavaScript, consideraremos os métodos e problemas de organização que surgem principalmente em aplicativos de grande porte.

Considere maneiras de manipular chaves para uma tarefa específica.
"Tarefa"
Imagine que em um projeto existente você precise implementar o processamento de entrada do teclado. Ao mesmo tempo, a interface do projeto e seus controladores, por razões puramente históricas, é claro, como elas são. E há o seguinte:
ParentController
no qual existem dois componentes com seus estados e estado. Controller1
e um elemento que usa CTRL+SHIFT+F
para pesquisar o site e Controller2
com seu elemento DOM, que é uma área local, na qual há uma pesquisa dentro dele. No entanto, eles podem estar simultaneamente na tela. Abaixo estão algumas maneiras de resolver esse problema.
1. “ KeyboardEvent e seu processamento manual”
Os objetos KeyboardEvent descrevem como o usuário interage com o teclado. Cada evento é descrito por uma chave; O tipo de evento (keydown, keypress ou keyup) determina o tipo de ação produzida.
Parece ótimo, certo? Vamos dar uma olhada.
Considere a interceptação de tecla CTRL+SHIFT+F
, geralmente correspondendo a uma chamada de pesquisa global.
element.addEventListener('keypress', (event) => { const keyName = event.key;
Agora, aplicável à nossa tarefa, você pode fazer duas maneiras (por exemplo)
Realize a interceptação de chaves nos controladores 1 e 2 separadamente
Isso levará ao fato de que, dependendo da ordem no DOM, pode ser necessário useCapture
para garantir que o processamento do Controller2 e, em seguida, Controller1 tenha useCapture
. Portanto, você obtém lógica isolada, mas se o aplicativo é complexo e existem muitos desses controladores, essa solução não é boa porque alguns podem estar simultaneamente na tela e podem ter sua própria ordem de processamento rigorosa, o que não depende de sua posição na árvore DOM. (veja borbulhando e capturando )
Captura de chave no CommonController
Uma solução alternativa seria manipular cliques em um controlador pai comum, que sabe exatamente quando mostrar seus filhos, controlados pelo primeiro e segundo controladores. Isso, ao aumentar os controladores filhos, não causará dificuldades na captura de eventos e na decisão de qual controlador processar as chaves. No entanto, haverá outro problema - grosso if
aparecer no controlador pai, que lida com todos os casos possíveis. Para aplicações grandes, esta solução não é adequada, porque em algum momento, pode aparecer outro Controller
que não é filho do ParentController
então você terá que ParentController
manipulador um nível acima para o pai comum e assim por diante ... Até que mais cedo ou mais tarde um dos controladores comece a saber muito sobre os elementos dentro dele.

De fato, apenas 80% dos navegadores são capazes de trabalhar com o KeboardEvent.key
; no restante, você precisará operar o KeboardEvent.keyCode
: Number
com códigos de chave. O que complica muito a vida. Aqui vale a pena descrever as desvantagens dessa abordagem.
Contras:
- A organização do código não é muito conveniente, requer um cartão de códigos de caracteres e seu equivalente em texto e outros utilitários que reduzem a quantidade de código nos manipuladores.
- 80% O suporte dos navegadores para trabalhar com símbolos sem usar seus códigos ainda não é suficiente.
- Sobreposição usando
useCapture
um manipulador para outro. - Se houver ganchos com
useCapture
e elementos aninhados com os mesmos manipuladores
a depuração é difícil. - Escalabilidade ruim.
Mas, nativamente, não há dependências e bibliotecas desnecessárias
A seguir, falaremos sobre duas bibliotecas, uma das quais foi projetada para resolver seus próprios problemas semelhantes.
2. "Usando a biblioteca HotKeys "
Três mil estrelas no github, tamanho modesto e falta de dependências. Um fabricante chinês, promete-nos uma solução que irá agradar a todos. Mas não vamos nos apressar. Vamos tentar resolver nosso problema com sua ajuda.
A sintaxe já parece muito menor, e o chip principal para resolver o problema estará mostrando diretamente os componentes dos controladores 1 e 2 na tela. Depois de vasculhar um pouco o código da biblioteca, é fácil perceber que os manipuladores formam uma pilha que é preenchida ou limpa à medida que são registrados, ou seja, aparecendo na tela (digamos que um elemento com um manipulador que apareceu depois do existente tenha prioridade na fila para processar teclas de atalho).
Muitas vezes acontece que o elemento que deve interceptar o processamento aparece mais tarde. Nesse caso, podemos espalhar com segurança a lógica da manipulação de cliques para cada um dos controladores. E outros chips, como escopos, nos ajudarão a separar um fluxo de cliques do outro. Mas no caso em que a ≠
- os mesmos problemas surgem como no eventListener nativo. Teremos que colocar tudo em um controlador pai comum.
Além disso, muitas vezes acontece que você precisa bloquear o comportamento padrão, mas o evento não é considerado processado (em outras palavras, não há entendimento inequívoco se o evento é processado ou não, se o recebemos) ou deve ser processado por dois controladores simultaneamente. Um deles causará uma reação ao comportamento e o outro simplesmente levará em conta que o evento foi.
Total de vantagens:
- O escopo permite separar fluxos.
- A sintaxe é clara e curta.
- A ordem determina a aparência do elemento, não a posição no DOM.
- Tamanho e falta de dependências.
Contras:
- Somente um escopo pode ser processado por vez
- A depuração ainda é difícil devido a chamadas de função no loop, talvez não seja conhecido em qual manipulador
perdido evento tratado - A declaração de que o evento é processado se tiver o sinalizador defaultPrevented e sua distribuição for interrompida não é verdadeira.
- Funções globais de registro de chamadas e cancelamento de inscrição de eventos
É adequado para resolver tarefas típicas, mas haverá problemas com a gravação de um terminal de negociação ou de um grande painel de administração, com certeza a depuração.
Como resultado de muitas tentativas e tentativas de usar a solução de outra pessoa, tive que fazer minha a bicicleta uma biblioteca que ajudará, em primeiro lugar, a estrear normalmente, preservar todas as melhores propriedades das populares e trazer algo novo.
Que tarefas foram resolvidas na criação?
- Princípio reativo de operação
- Manipuladores de depuração simples
- Status inequívoco de processamento de eventos
- Plataforma cruzada
- Conveniência de importação e falta de funções globais
- Sem acesso direto à janela ao conectar
- Não há necessidade de chamar
preventDefault
ou stopPropagation
Aplicável à nossa tarefa, a solução coincide completamente com a biblioteca anterior. Uma separação completa da lógica de processamento sem muito conhecimento um do outro ainda não aconteceu, mas muito se tornou mais simples e compreensível. Graças ao seguinte:
- Ainda não há ligação ao DOM (com exceção de um ouvinte) e a pilha de manipuladores é preenchida dependendo da ordem em que eles estão registrados.
scope
imediatamente se recusaram a usar o scope
para isolamento. não está claro quais tarefas ele resolve e parece que isso apenas complica a arquitetura.- A depuração e a próxima função sobre ela provavelmente valem mais ...
- Mutações nos eventos dos dados que ele carrega em
event.detail
Os manipuladores de depuração são organizados de forma que um callstack
de chamada seja formado antes da chamada. Ele permite que você veja no console toda a cadeia do evento, do primeiro manipulador ao próximo.
next () - Uma chamada de função significa que o evento não foi processado e será passado para o próximo manipulador. Um contrato bastante familiar que se aplica a manipuladores intermediários ou middleware em express
. Portanto, você sempre saberá se o evento foi processado ou apenas foi alterado ou "levado em consideração".

É assim que a pilha de chamadas se parece se você definir um ponto de interrupção em uma delas.
Bem, sobre os contras:
- Ainda não há nenhum texto datilografado.
- Sem escopos - não é possível criar um site de tela dividida)
- Uma combinação durante o registro (isso não é
CMD+F,CMD+V,T
não entenderá a vírgula)