Umgang mit Tastenanschlägen, auch als Verknüpfungen bezeichnet, und Debugging

Hallo! Wir werden über Hotkeys in WEBAPI + JavaScript sprechen und deren Organisationsmethoden und Probleme betrachten, die hauptsächlich in großen Anwendungen auftreten.


Überlegen Sie, wie Sie mit Schlüsseln für eine bestimmte Aufgabe umgehen können.


"Aufgabe"


Stellen Sie sich vor, Sie müssen in einem vorhandenen Projekt die Verarbeitung von Tastatureingaben implementieren. Gleichzeitig die Projektschnittstelle und ihre Controller, natürlich aus rein historischen Gründen, wie sie sind. Und es gibt Folgendes:


ParentController in dem zwei Komponenten mit ihrem Status und Status vorhanden sind. Controller1 und ein Element, das die Site mit CTRL+SHIFT+F durchsucht, und Controller2 mit seinem DOM-Element, einem lokalen Bereich, in dem eine Suche durchgeführt wird. Sie können jedoch gleichzeitig auf dem Bildschirm angezeigt werden. Im Folgenden finden Sie einige Möglichkeiten, um dieses Problem zu lösen.


1. " KeyboardEvent und seine manuelle Verarbeitung"


KeyboardEvent-Objekte beschreiben, wie der Benutzer mit der Tastatur interagiert. Jedes Ereignis wird durch einen Schlüssel beschrieben. Die Art des Ereignisses (Tastendruck, Tastendruck oder Tastendruck) bestimmt die Art der erzeugten Aktion.


Hört sich toll an, oder? Schauen wir uns das genauer an.
Betrachten Sie die CTRL+SHIFT+F , die normalerweise einem globalen Suchanruf entspricht.


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

Für unsere Aufgabe können Sie jetzt zwei Möglichkeiten wählen (zum Beispiel).


Führen Sie das Abfangen der Schlüssel in den Steuerungen 1 und 2 separat durch


Dies führt dazu, dass Sie abhängig von der Reihenfolge im DOM möglicherweise useCapture müssen, useCapture , dass die Verarbeitung von Controller2 und dann von Controller1 erfolgt. Sie erhalten also eine isolierte Logik, aber wenn die Anwendung komplex ist und es viele solcher Controller gibt, ist diese Lösung nicht gut, weil Einige können gleichzeitig auf dem Bildschirm angezeigt werden und eine eigene strenge Verarbeitungsreihenfolge haben, die nicht von ihrer Position im DOM-Baum abhängt. (siehe Sprudeln und Erfassen )


Schlüsselerfassung in CommonController


Eine alternative Lösung wäre, Klicks in einem gemeinsamen übergeordneten Controller zu verarbeiten, der genau weiß, wann seine untergeordneten Controller angezeigt werden sollen, die vom ersten und zweiten Controller gesteuert werden. Dies erhöht beim Erhöhen der untergeordneten Controller keine Schwierigkeiten beim Abfangen von Ereignissen und beim Entscheiden, für welchen Controller die Schlüssel verarbeitet werden sollen. Es wird jedoch ein anderes Problem geben - ein dickes if im übergeordneten Controller angezeigt, das alle möglichen Fälle behandelt. Für große Anwendungen ist diese Lösung nicht geeignet, weil Irgendwann wird möglicherweise ein anderer Controller angezeigt, der kein ParentController des ParentController Dann müssen Sie ParentController Handler um eine Ebene auf das gemeinsame übergeordnete ParentController und so weiter ... Bis früher oder später einer der Controller zu viel über die darin enthaltenen Elemente weiß.



Tatsächlich können nur 80% der Browser mit KeboardEvent.key . Im übrigen müssen Sie KeboardEvent.keyCode : Number mit Schlüsselcodes bedienen. Was das Leben sehr kompliziert macht. Hier lohnt es sich, die Nachteile dieses Ansatzes zu beschreiben.


Nachteile:


  • Die Organisation des Codes ist nicht sehr bequem, es sind eine Karte mit Zeichencodes und deren Textäquivalenten sowie andere Dienstprogramme erforderlich, die die Codemenge in den Handlern reduzieren.
  • 80% Unterstützung durch Browser für die Arbeit mit Symbolen ohne Verwendung ihrer Codes reicht immer noch nicht aus.
  • Überlappung mit useCapture einem Handler zum anderen.
  • Wenn es Hooks mit useCapture und verschachtelte Elemente mit denselben useCapture gibt
    Das Debuggen ist schwierig.
  • Schlechte Skalierbarkeit.

Aber nativ gibt es keine unnötigen Abhängigkeiten und Bibliotheken


Als nächstes werden wir über zwei Bibliotheken sprechen, von denen eine entwickelt wurde, um ihre eigenen ähnlichen Probleme zu lösen.


2. "Verwenden der HotKeys- Bibliothek"


Dreitausend Sterne auf Github, bescheidene Größe und fehlende Abhängigkeiten. Ein chinesischer Hersteller verspricht uns eine Lösung, die jedem gerecht wird. Aber lasst uns nicht eilen. Versuchen wir, unser Problem mit seiner Hilfe zu lösen.


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

Die Syntax sieht bereits viel kürzer aus, und der Hauptchip zur Lösung des Problems zeigt die Komponenten der Controller 1 und 2 direkt auf dem Bildschirm an. Nachdem Sie ein wenig im Code der Bibliothek gestöbert haben, ist es leicht zu bemerken, dass die Handler einen Stapel bilden, der gefüllt oder gelöscht wird, wenn sie registriert werden oder auf dem Bildschirm angezeigt werden (Angenommen, ein Element mit einem Handler, der später als der vorhandene angezeigt wird, hat in der Warteschlange Priorität für die Verarbeitung von Hotkeys).


Es kommt häufig vor, dass das Element, das die Verarbeitung abfangen soll, später angezeigt wird. In diesem Fall können wir die Logik der Behandlung von Klicks sicher auf jeden der Controller übertragen. Andere Chips wie Scopes helfen uns dabei, einen Klickstrom von einem anderen zu trennen. In dem Fall, in dem die , treten dieselben Probleme auf wie bei nativen eventListener. Wir müssen alles in einen gemeinsamen übergeordneten Controller einfügen.


Darüber hinaus kommt es häufig vor, dass Sie das Standardverhalten blockieren müssen, das Ereignis jedoch nicht als verarbeitet betrachtet wird (mit anderen Worten, es gibt kein eindeutiges Verständnis, ob das Ereignis verarbeitet wird oder nicht, wenn wir es empfangen haben), oder es muss von zwei Controllern gleichzeitig verarbeitet werden. Einer davon löst eine Reaktion auf das Verhalten aus, der andere berücksichtigt einfach, dass es sich um ein Ereignis handelt.


Insgesamt Pluspunkte:


  • Mit Scope können Sie Streams trennen.
  • Die Syntax ist klar und kurz.
  • Die Reihenfolge bestimmt das Erscheinungsbild des Elements, nicht die Position im DOM.
  • Größe und fehlende Abhängigkeiten.

Nachteile:


  • Es kann jeweils nur ein Bereich verarbeitet werden
  • Das Debuggen ist aufgrund von Funktionsaufrufen in der Schleife immer noch schwierig. Es ist möglicherweise nicht bekannt, auf welchem ​​Handler verloren Ereignis behandelt
  • Die Aussage, dass das Ereignis verarbeitet wird, wenn es das Flag defaultPrevented hat und seine Verteilung unterbrochen ist, ist nicht wahr.
  • Globale Funktionen zur Anrufregistrierung und zum Abbestellen von Ereignissen

Es eignet sich zum Lösen typischer Aufgaben, aber es wird Probleme beim Schreiben eines Handelsterminals oder eines großen Admin-Panels geben, um sicher zu debuggen.


3. "Verwenden der Stapelverknüpfungsbibliothek "


Aufgrund vieler Rechen und Versuche, die Lösung eines anderen zu verwenden, musste ich meine machen Fahrrad Eine Bibliothek, die zuallererst dabei hilft, normal zu debütieren, die besten Eigenschaften der populären zu bewahren und etwas Neues zu bringen.


Welche Aufgaben wurden bei der Erstellung gelöst?


  • Reaktives Funktionsprinzip
  • Einfache Debugging-Handler
  • Eindeutiger Status der Ereignisverarbeitung
  • Plattformübergreifend
  • Bequemlichkeit des Imports und Mangel an globalen Funktionen
  • Kein direkter Fensterzugriff beim Verbinden
  • Sie müssen nicht preventDefault oder stopPropagation

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

Für unsere Aufgabe anwendbar, stimmt die Lösung vollständig mit der vorherigen Bibliothek überein. Eine vollständige Trennung der Verarbeitungslogik ohne zu viel gegenseitiges Wissen ist noch nicht geschehen, aber vieles ist einfacher und verständlicher geworden. Vielen Dank an:


  • Es besteht immer noch keine Bindung zum DOM (mit Ausnahme eines Listeners), und der Stapel von Handlern wird abhängig von der Reihenfolge, in der sie registriert sind, gefüllt.
  • scope weigerten sich sofort, scope für Isolation zu nutzen. Es ist nicht klar, welche Aufgaben es löst, und es scheint, dass es die Architektur nur kompliziert.
  • Das Debuggen und die nächste Funktion darüber sind wahrscheinlich mehr wert ...
  • Mutationen in den Ereignissen der Daten, die er in event.detail trägt

Debugging- Handler sind so angeordnet, dass aus ihnen vor dem Aufruf ein callstack gebildet wird. Sie können in der Konsole die gesamte Kette des Ereignisses vom ersten bis zum nächsten Handler anzeigen.


next () - Ein Funktionsaufruf bedeutet, dass das Ereignis nicht verarbeitet wurde und an den nächsten Handler übergeben wird. Ein ziemlich vertrauter Vertrag, der für Intermediate-Handler oder Middleware in express . So wissen Sie immer, ob das Ereignis verarbeitet oder nur mutiert oder "berücksichtigt" wird.



So sieht der Aufrufstapel aus, wenn Sie in einem von ihnen einen Haltepunkt festlegen.


Nun, über die Nachteile:


  • Es gibt noch keine Typoskripte.
  • Keine Bereiche - eine Splitscreen-Site kann nicht erstellt werden.
  • Eine Kombination während der Registrierung (dies ist nicht CMD+F,CMD+V,T versteht das Komma nicht)

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


All Articles