Manejo de pulsaciones de teclado, también conocidos como atajos y depuración

Hola Hablaremos sobre las teclas de acceso rápido en WEBAPI + JavaScript, consideremos sus métodos de organización y los problemas que surgen principalmente en aplicaciones grandes.


Considere formas de manejar las claves para una tarea específica.


"Tarea"


Imagine que en un proyecto existente necesita implementar el procesamiento de entrada de teclado. Al mismo tiempo, la interfaz del proyecto y sus controladores, por razones puramente históricas, por supuesto, tal como son. Y hay lo siguiente:


ParentController en el que hay dos componentes con sus estados y estado. Controller1 y un elemento que usa CTRL+SHIFT+F para buscar en el sitio, y Controller2 con su elemento DOM, que es un área local, en el que hay una búsqueda dentro de él. Sin embargo, pueden estar simultáneamente en la pantalla. A continuación hay algunas formas de resolver este problema.


1. " KeyboardEvent y su procesamiento manual"


Los objetos KeyboardEvent describen cómo interactúa el usuario con el teclado. Cada evento se describe con una clave; El tipo de evento (keydown, keypress o keyup) determina el tipo de acción producida.


¿Suena genial verdad? Echemos un vistazo más de cerca.
Considere CTRL+SHIFT+F intercepción de pulsación de tecla, que generalmente corresponde a una llamada de búsqueda global.


 element.addEventListener('keypress', (event) => { const keyName = event.key; //        // ..     SHIFT      if (event.ctrlKey && event.shiftKey && event.key.toLowerCase() === 't') { alert('CTRL+SHIFT+T pressed'); } }); 

Ahora, aplicable a nuestra tarea, puede hacer dos formas (por ejemplo)


Realice la interceptación de llaves en los controladores 1 y 2 por separado


Esto conducirá al hecho de que, dependiendo del orden en el DOM, es posible que deba useCapture para garantizar que se procesará el Controller2 y luego el Controller1. Entonces obtienes lógica aislada, pero si la aplicación es compleja y hay muchos de esos controladores, esta solución no es buena porque algunos pueden estar simultáneamente en la pantalla y pueden tener su propio orden de procesamiento estricto, que no depende de su posición en el árbol DOM. (ver burbujeando y capturando )


Captura de clave en CommonController


Una solución alternativa sería manejar los clics en un controlador principal común, que sabe exactamente cuándo mostrar sus elementos secundarios, controlados por el primer y el segundo controlador. Esto al tiempo que aumenta los controladores secundarios no causará dificultades para detectar eventos y decidir para qué controlador procesar las claves. Sin embargo, habrá otro problema: un grueso if aparece en el controlador principal, que maneja todos los casos posibles. Para aplicaciones grandes, esta solución no es adecuada, porque en algún momento, puede aparecer otro Controller que no sea hijo del ParentController luego tendrá que ParentController controlador un nivel hasta su padre común y así sucesivamente ... Hasta que tarde o temprano uno de los controladores comience a saber demasiado sobre los elementos que contiene.



De hecho, solo el 80% de los navegadores pueden trabajar con KeboardEvent.key , en todo lo demás necesitará operar KeboardEvent.keyCode : Number con códigos clave. Lo que complica mucho la vida. Aquí vale la pena ir a una descripción de las desventajas de este enfoque.


Contras:


  • La organización del código no es muy conveniente, requiere una tarjeta de códigos de caracteres y su equivalente de texto, y otras utilidades que reducen la cantidad de código en los controladores.
  • El 80% de soporte por parte de los navegadores para trabajar con símbolos sin usar sus códigos todavía no es suficiente.
  • Superposición usando useCapture un controlador a otro.
  • Si hay ganchos con useCapture y elementos anidados con los mismos controladores
    La depuración es difícil.
  • Escalabilidad deficiente.

Pero de forma nativa, no hay dependencias y bibliotecas innecesarias


A continuación, hablaremos de dos bibliotecas, una de las cuales fue diseñada para resolver sus propios problemas similares.


2. "Uso de la biblioteca HotKeys "


Tres mil estrellas en github, tamaño modesto y falta de dependencias. Un fabricante chino, nos promete una solución que se adaptará a todos. Pero no nos apuremos. Tratemos de resolver nuestro problema con su ayuda.


 //   hotkeys('ctrl+shift+f', function(event, handler){ alert('CTRL+SHIFT+T pressed'); }); 

La sintaxis parece mucho más corta y el chip principal para resolver el problema mostrará directamente los componentes de los controladores 1 y 2 en la pantalla. Habiendo hurgado un poco en el código de la biblioteca, es fácil notar que los manejadores forman una pila que se llena o borra a medida que se registran o que aparecen en la pantalla (Digamos que un elemento con un manejador que apareció más tarde que el existente tendrá prioridad en la cola para procesar las teclas de acceso rápido).


A menudo sucede que el elemento que debe interceptar el procesamiento aparece más tarde. En este caso, podemos difundir con seguridad la lógica del manejo de los clics a cada uno de los controladores. Y otros chips, como los ámbitos, nos ayudarán a separar una secuencia de clics de otra. Pero en el caso de que el ≠ , surgen los mismos problemas que en los eventos nativos. Tendremos que poner todo en un controlador principal común.


Además, a menudo sucede que necesita bloquear el comportamiento predeterminado, pero el evento no se considera procesado (en otras palabras, no existe una comprensión inequívoca de si el evento se procesa o no si lo recibimos) o debe ser procesado por dos controladores simultáneamente. Uno de los cuales causará una reacción al comportamiento, y el otro simplemente tendrá en cuenta que el evento fue.


Ventajas totales:


  • Alcance le permite separar las transmisiones.
  • La sintaxis es clara y corta.
  • El orden determina la apariencia del elemento, no la posición en el DOM.
  • Tamaño y falta de dependencias.

Contras:


  • Solo se puede procesar un alcance a la vez
  • La depuración sigue siendo difícil debido a las llamadas de función en el bucle, es posible que no se sepa en qué controlador perdido evento manejado
  • La afirmación de que el evento se procesa si tiene el indicador DefaultPrevented y se interrumpe su distribución no es verdadera.
  • Funciones globales de registro de llamadas y baja de eventos

Es adecuado para resolver tareas típicas, pero habrá problemas al escribir un terminal comercial o un panel de administración grande, para una depuración segura.


3. "Uso de la biblioteca de atajos de pila "


Como resultado de muchos rastrillos e intentos de usar la solución de otra persona, tuve que hacer mi la bici una biblioteca que ayudará, en primer lugar, a debutar normalmente, preservar las mejores propiedades de las populares y traer algo nuevo.


¿Qué tareas se resolvieron en la creación?


  • Principio de funcionamiento reactivo.
  • Controladores de depuración simples
  • Estado de procesamiento de eventos inequívoco
  • Multiplataforma
  • Conveniencia de importación y falta de funciones globales
  • No hay acceso directo a la ventana cuando se conecta
  • No es necesario llamar a preventDefault o stopPropagation

 //  this.shortcuts = shortcuts({ 'CMD+SHIFT+F': function (event, next) { alert('CMD+SHIFT+F pressed'); } }); //  this.shortcuts.destroy(); 

Aplicable a nuestra tarea, la solución coincide completamente con la biblioteca anterior. Todavía no se ha producido una separación completa de la lógica de procesamiento sin demasiado conocimiento el uno del otro, pero mucho se ha vuelto más simple y más comprensible. Gracias a lo siguiente:


  • Todavía no hay ningún enlace con el DOM (con la excepción de un oyente) y la pila de controladores se llena según el orden en que se registran.
  • Inmediatamente se negaron a utilizar el scope para el aislamiento. no está claro qué tareas resuelve y parece que solo complica la arquitectura.
  • La depuración y la siguiente función al respecto probablemente valen más ...
  • Mutaciones en los eventos de los datos que lleva en event.detail

Los controladores de depuración están dispuestos de tal manera que se forma una callstack partir de ellos antes de la llamada. Le permite ver en la consola toda la cadena del evento desde el primer controlador hasta el siguiente.


next () : una llamada de función significa que el evento no se ha procesado y se pasará al siguiente controlador. Un contrato bastante familiar que se aplica a los controladores intermedios o middleware en express . Por lo tanto, siempre sabrá si el evento se procesa o simplemente se muta o "se tiene en cuenta".



Así es como se ve la pila de llamadas si establece un punto de interrupción en uno de ellos.


Bueno, sobre los contras:


  • Todavía no hay textos mecanografiados.
  • Sin ámbitos: no se puede crear un sitio de pantalla dividida)
  • Una combinación durante el registro (esto no es CMD+F,CMD+V,T no entenderá la coma)

Source: https://habr.com/ru/post/438770/


All Articles