Wenn ich anfange, eine Schnittstelle zu entwerfen, stoße ich immer auf das Problem, dass Event-Handler direkt an Schaltflächen angehängt sind, was die Flexibilität der Komponenteninteraktion einschränkt. Das Problem besteht darin, dass Standardschaltflächen kein anderes Verhalten bieten können. Was ich brauche, ist Logikisolation und dynamisches Aktionsmanagement, die bei der Verwendung von Standardschaltflächen „out of the box“ nicht verfügbar sind. In diesem Artikel werde ich eine Lösung vorschlagen, wie Schaltflächen mithilfe von Webkomponenten und dem „Befehls“-Muster angepasst werden können, wodurch neue Möglichkeiten für flexiblere und skalierbarere Schnittstellen eröffnet werden.
Wenn wir an eine Schaltfläche denken, nehmen wir sie normalerweise als grafisches Steuerelement wahr, das eine einfache Möglichkeit bietet, ein Ereignis, eine Aktion oder eine Änderung des Schnittstellenstatus auszulösen. Dies ist eine sehr einfache und praktische Definition, die zu unserem alltäglichen Verständnis von Benutzeroberflächenelementen in Webanwendungen passt.
Wenn wir jedoch im Kontext der Webentwicklung auf eine Schaltfläche stoßen, wenn HTML und JavaScript beteiligt sind, fällt uns als Erstes das Standard-Tag ein, das am häufigsten verwendete Werkzeug zum Erstellen von Schaltflächen auf Webseiten. Dieses Tag sieht normalerweise so aus:
<button onclick="myFunction()">Click me</button>
Aber wenn wir darüber nachdenken, spiegelt dieses Tag, obwohl es als Schaltfläche dient, nicht alle möglichen Aspekte und Funktionen wider, die eine Schaltfläche im breiteren Kontext der Benutzerinteraktion mit einer Schnittstelle ausführen kann.
Bei näherer Betrachtung der Definition einer Schaltfläche fällt möglicherweise auf, dass sie keine Informationen darüber liefert, wie die Schaltfläche aussehen, sich verhalten oder eine Aktion auslösen soll. In diesem Zusammenhang gibt es kein klares Verständnis dafür, was mit den Worten „ein einfacher Weg“ zum Auslösen einer Aktion gemeint ist und wie die Verbindung zwischen der Schaltfläche und der Aktion hergestellt wird. Wir sehen nur die Grundstruktur einer Schaltfläche, die beim Klicken eine Methode aufruft. Doch in Wirklichkeit verbirgt sich hinter dieser Einfachheit ein viel breiteres Spektrum an Möglichkeiten und Ansätzen. Und so stellt sich die Frage: Vielleicht ist der Button mehr als nur das Tag, das wir im obigen Beispiel sehen?
Lassen Sie uns das Konzept eines Knopfes aus einer philosophischeren Perspektive betrachten und uns mit seinem Wesen und seiner Funktion befassen. Was stellt eine Schaltfläche wirklich dar? Wenn wir das Wesen eines Kruges als seine Leere betrachten, liegt das Wesen eines Knopfes in seiner Fähigkeit, eine Aktion auszulösen. Eine Schaltfläche ist nicht nur ein Element der Benutzeroberfläche; Dabei handelt es sich um einen Mechanismus, der einen bestimmten Prozess auslöst, der bereits im Kontext der Anwendung vorhanden ist. Die auszuführende Aktion geschieht innerhalb der Anwendung, im Kontext des gesamten Systems, aber die Auslösung dieser Aktion – ihr Start – ist die Funktion der Schaltfläche. Daher sehen wir, dass die Schaltfläche als eine Art Auslöser dient und eine Aktion in einem breiteren externen Systemkontext auslöst.
Wenn ein Benutzer auf eine Schaltfläche klickt, erwartet er, dass dieser Klick zu einer bestimmten Aktion führt. Dem Button wird somit die Verantwortung für die Auslösung dieser Aktion zugeschrieben. Mit anderen Worten: Die Schaltfläche wird zum Bindeglied zwischen dem Benutzer und den darauf folgenden Aktionen. Es ist jedoch wichtig zu beachten, dass die Methode oder Funktion, die die Aktion tatsächlich ausführt, nicht wissen sollte, dass die Schaltfläche sie ausgelöst hat. Diese Unterscheidung zwischen dem, was die Aktion auslöst, und dem, was sie ausführt, ist ein entscheidender Aspekt, der es uns ermöglicht, Flexibilität und einfache Interaktion in komplexeren Systemen aufrechtzuerhalten.
Wenn die Schaltfläche die Aktion direkt ausführt oder wenn die Methode zur Implementierung der Aktion von der Schaltfläche selbst abhängt, haben wir es mit einem ziemlich komplexen und voneinander abhängigen System zu tun. Wenn wir ein solches System vereinfachen wollen, ist es notwendig, es in einfachere, unabhängige Teile zu zerlegen. Und hier kommen wir zu dem Schluss, dass die Vereinfachung des Prozesses der Initiierung einer Aktion in erster Linie darin besteht, den Initiierungsprozess von der Aktion selbst zu trennen. Und da im Kontext von JavaScript der Initiator oft als Ereignis bezeichnet wird, sprechen wir speziell davon, das Ereignis als Initiator von der Logik zu trennen, die die Aktion ausführt.
Warum ist es wichtig, das Ereignis vom Handler zu trennen?
Zuallererst verbessert die Trennung von Ereignissen und Handlern die Lesbarkeit des Codes erheblich und fördert die Erstellung modularerer Lösungen. Wenn die Schaltflächenlogik und ihr Handler miteinander verflochten sind oder, noch schlimmer, wenn der Handler eine anonyme Funktion ist, wird es extrem schwierig, den Code zu lesen und zu analysieren. Dies kann zu Problemen bei der Pflege und Aktualisierung des Projekts führen, da es zu einer herausfordernden Aufgabe wird, zu verstehen, was die Schaltfläche tatsächlich bewirkt und welche Änderungen erforderlich sind. Wenn der Handler hingegen in eine separate, gut benannte Funktion extrahiert wird, die die ausgeführte Aktion klar widerspiegelt, wird die Struktur des Codes transparenter. Der Entwickler versteht sofort, was passiert, wenn auf die Schaltfläche geklickt wird, und kann das Verhalten des Elements einfacher ändern, ohne sich mit der restlichen Logik befassen zu müssen. Somit vereinfacht die Trennung sowohl das Lesen als auch das Vornehmen von Änderungen am Code.
Zweitens eröffnet die Trennung der Ereignislogik und des Handlers Möglichkeiten für die Wiederverwendung von Handlern in verschiedenen Teilen der Anwendung. Wenn der Handler in einer eigenen Funktion platziert wird, kann er nicht nur auf eine Schaltfläche, sondern auf viele andere mit ähnlichem Verhalten angewendet werden. Beispielsweise können mehrere Schaltflächen, die dieselbe Aktion ausführen, denselben Handler verwenden, was die Codeduplizierung reduziert und die Effizienz erhöht. Darüber hinaus kann der Handler nicht nur über die Schaltfläche, sondern auch auf andere Weise ausgelöst werden, beispielsweise durch Programmaufrufe oder Aktionen, die von anderen Teilen der Schnittstelle initiiert werden. Dadurch wird die Funktionalität Ihrer Anwendung erheblich erweitert und ihre Flexibilität und Skalierbarkeit erhöht.
Drittens ermöglicht die Trennung von Ereignissen und Handlern mehr Flexibilität bei den Schaltflächen selbst. Wenn das Verhalten der Schaltfläche nun nicht innerhalb der Schaltfläche selbst, sondern über einen separaten Handler bestimmt wird, ist es einfach, ihre Aktionen je nach Situation zu ändern oder neu zuzuweisen. Dies ist besonders wichtig bei Projekten mit dynamischen Schnittstellen, bei denen sich das Verhalten von Elementen als Reaktion auf Benutzeraktionen oder Änderungen im Anwendungsstatus ändern kann. Dieser Ansatz ermöglicht eine einfache Anpassung der Schnittstelle an sich ändernde Anforderungen, ohne die gesamte Codestruktur zu stören.
Viertens ist die Trennung von Ereignissen und Handlern entscheidend für die Testbarkeit, insbesondere in großen Projekten. Wenn Event-Handler in separate Funktionen extrahiert werden, wird das Testen dieser wesentlich einfacher, da sie unabhängig von der Schnittstelle getestet werden können. Sie können den Handler isolieren und testen, wie er mit verschiedenen Parametern funktioniert, ohne sich Gedanken über die Interaktion mit anderen Teilen der Schnittstelle machen zu müssen. Dies erleichtert das Testen, verbessert die Zuverlässigkeit und Stabilität der Anwendung und minimiert gleichzeitig die Fehlerwahrscheinlichkeit.
Die Trennung von Schaltflächenereignis und Handler ist ein wichtiger Schritt hin zu einer saubereren, flexibleren und wartbareren Codearchitektur. Dies ist besonders wichtig bei komplexen Projekten, bei denen die Interaktionen zwischen Schnittstellenelementen immer komplexer und voneinander abhängig werden. Dieser Ansatz trägt zur Verbesserung der Systemstabilität bei, erleichtert die Erweiterung und Änderung der Anwendung und verringert das Risiko von Fehlern, die bei diesen Änderungen auftreten.
Ein Beispiel für die Trennung des Ereignisses einer Schaltfläche von ihrem Handler finden Sie in jedem Einsteigerhandbuch.
<button onclick="myFunction()">Click me</button>
Wenn Schaltflächen nicht nur den Kontext einer Interaktion, sondern auch die Absicht des Benutzers explizit innerhalb des Ereignisses vermitteln könnten, würde dies die Architektur erheblich vereinfachen. Handler könnten sich auf die Ausführung von Aufgaben konzentrieren, anstatt den Ereignissen Logik zuzuweisen.
Dies unterstreicht die Notwendigkeit, sich vom traditionellen Verständnis eines Buttons als bloßem Event-Initiator zu lösen. Stattdessen wird die Einführung eines fortschrittlicheren Modells vorgeschlagen, bei dem die Schaltfläche als Brücke zwischen Benutzerabsicht und Anwendungslogik fungiert.
Um ein erweitertes Modell für die Ereignisbehandlung zu erstellen, können wir das Befehlsmuster nutzen, das die Verknüpfung von Ereignissen mit der Anwendungslogik auf einer höheren Abstraktionsebene ermöglicht. Dies kann durch die Einführung einer Ebene erreicht werden, die gewöhnliche Ereignisse in Befehle wie saveDocument oder deleteItem umwandelt. Mit diesem Ansatz wird ein Ereignis zu mehr als nur einem Signal dafür, dass etwas geschehen ist – es verwandelt sich in das, was es sein soll: der Auslöser einer Aktion, wie weiter oben in diesem Artikel besprochen.
Aber das wirft eine Frage auf: Warum haben die Entwickler von JavaScript-Ereignissen das Befehlsmuster nicht von Anfang an implementiert? Warum wurden Veranstaltungen so konzipiert, wie sie jetzt sind? Und warum waren Veranstaltungen überhaupt notwendig?
Als HTML und verwandte Technologien wie DOM und JavaScript ursprünglich entwickelt wurden, bestand ihr Hauptziel darin, eine einfache Struktur für Hypertextdokumente zu schaffen, die Benutzern die Interaktion mit Webseiten ermöglichen würde. Zu diesem Zeitpunkt war die Benutzerinteraktion erheblich eingeschränkt, und das Ereignisverarbeitungsmodell war nicht darauf ausgelegt, komplexe Mechanismen wie das Befehlsmuster zu berücksichtigen. Es ist wichtig zu verstehen, dass das frühe Web entwickelt wurde, um die Erstellung und Verwaltung von Inhalten zu vereinfachen, und nicht, um ausgefeilte Tools für komplexe clientseitige Logik bereitzustellen.
In den 1990er Jahren, als HTML und das Web erstellt wurden, lag der Schwerpunkt auf der Bereitstellung einer unkomplizierten Möglichkeit zur Präsentation von Hypertextdokumenten mit minimaler Benutzerinteraktion. Das Hauptziel war die Datenübermittlung an Server und nicht die Ausführung komplexer Logik im Browser. Schaltflächen und Formulare dienten in erster Linie dem Versenden von Daten und nicht der Initiierung clientseitiger Prozesse. Die gesamte Berechnung und Datenverarbeitung wurde auf dem Server abgewickelt, wobei Schaltflächen als Schnittstellenelemente dienten, die die Datenübermittlung an das Backend auslösten.
Das Befehlsmuster erfordert eine ausgefeiltere Struktur, die eine klare Trennung zwischen der Schnittstelle und der Verarbeitungslogik sowie einen Mechanismus zur Angabe der genauen auszuführenden Aktion beinhaltet. Diese Ideen wurden erst später relevant, als der Bedarf an dynamischen Schnittstellen und größerer Interaktivität in Webanwendungen wuchs. Dynamische und komplexe Interaktionen, wie das Auslösen der clientseitigen Logik durch Ereignisse, erforderten neue Ansätze, einschließlich der Übernahme des Befehlsmusters.
Kann das Befehlsmuster heute auf Schaltflächen angewendet werden? Ja, das kann es. Während Standard-HTML-Schaltflächen das Befehlsmuster nicht direkt unterstützen, ermöglichen uns moderne Technologien wie benutzerdefinierte Ereignisse die Erstellung ähnlicher Mechanismen. Wir haben beispielsweise bereits untersucht, wie die Detaileigenschaft verwendet werden kann, um zusätzliche Daten mit Ereignissen zu übergeben.
Dieser Ansatz ist jedoch immer noch nicht ideal, da er die Erstellung separater Implementierungen für jede Schaltfläche in der Benutzeroberfläche erfordert. Dies erhöht die Komplexität und macht die Skalierung solcher Systeme schwieriger.
Die Nutzung von Webkomponenten zur Modernisierung von Schaltflächen und deren Ausrichtung auf das Befehlsmuster ist ein vielversprechender Ansatz, der sowohl die Architektur als auch die Flexibilität der Interaktionen in Ihrem Projekt erheblich verbessern kann. Webkomponenten bieten leistungsstarke Tools zum Erstellen wiederverwendbarer Schnittstellenelemente, die nahtlos in verschiedene Teile einer Anwendung integriert werden können.
Anstatt separate Handler für jede Schaltfläche zu schreiben, können Sie eine einheitliche Komponente erstellen, die als Schaltfläche fungiert und über die zusätzliche Möglichkeit verfügt, einen Befehl zu übergeben. Dieser Ansatz verbessert nicht nur die Struktur des Codes, sondern verbessert auch seine Lesbarkeit und Wartbarkeit.
Hier ist ein einfaches Beispiel für eine solche Komponente:
<button onclick="myFunction()">Click me</button>
Wenn eine Tastenkomponente eine Befehlskennung und möglicherweise zusätzliche Parameter überträgt, bildet sie die Grundlage für eine fortschrittlichere Architektur. In diesem Setup fungiert die Komponente, die die Schaltfläche enthält und ihre Ereignisse abonniert, im Wesentlichen als Controller, der den durch das Ereignis übergebenen Befehl verarbeitet.
In Architekturmustern wie MVC (Model-View-Controller) dient der Controller als Vermittler zwischen dem Modell, das die Daten darstellt, und der Ansicht, die die Benutzeroberfläche darstellt. Es empfängt Benutzereingaben, wie z. B. Tastenklicks, und verwaltet die daraus resultierenden Änderungen an den Daten oder dem Status, die dann in der Schnittstelle widergespiegelt werden.
Der Einsatz eines Controllers innerhalb einer Komponente bietet mehrere entscheidende Vorteile. Erstens kapselt es die Logik zum Ausführen von Befehlen und hält den Hauptanwendungscode frei von unnötiger Komplexität. Die Details der Implementierung bleiben im Controller selbst verborgen. Zweitens verbessert dieser Ansatz die Modularität und ermöglicht die Wiederverwendung von Schaltflächen, indem einfach verschiedene Befehle und Parameter übergeben werden. Außerdem wird die Kopplung innerhalb der Anwendung reduziert, da Änderungen an der Befehlsverarbeitungslogik nur Änderungen innerhalb der Steuerung erfordern, ohne dass sich dies auf andere Teile des Systems auswirkt. Schließlich bieten Controller erhebliche Flexibilität. Sie können sowohl einfache Befehle wie „Speichern“ oder „Löschen“ als auch komplexere Aktionen verarbeiten, während die Schaltflächenkomponente einfach bleibt und sich ausschließlich auf ihre Hauptaufgabe konzentriert.
Diese Architektur ermöglicht eine saubere Trennung der Belange. Die Schaltflächenkomponente gibt ein benutzerdefiniertes Ereignis aus, das den Befehl und seine relevanten Daten enthält, während die übergeordnete Komponente als Controller auf dieses Ereignis wartet. Der Controller verarbeitet den Befehl, interagiert bei Bedarf mit dem Datenmodell und aktualisiert die Benutzeroberfläche entsprechend. Dieser Ansatz führt zu einer saubereren, skalierbareren Architektur, die einfacher zu erweitern und zu warten ist, während die Tastenkomponenten wiederverwendbar und unabhängig von der Logik bleiben, die sie auslösen.
Zusammenfassend lässt sich sagen, dass der Ansatz, bei dem eine Schaltfläche nicht nur eine Aktion auslöst, sondern durch ein Ereignis auch einen Befehl mit den erforderlichen Daten übermittelt, ein hervorragendes Beispiel für die Anwendung des „Befehl“-Musters ist. Diese Methode verbessert die Organisation der Schnittstelleninteraktion erheblich, indem sie die Logik der Befehlsausführung von den Schnittstellenelementen trennt und so die Flexibilität und Skalierbarkeit von Anwendungen erhöht.
Allerdings ist ein solches Vorgehen in der Praxis noch relativ unüblich. Anstatt die leistungsstarken Funktionen von Webkomponenten zu nutzen, um universelle und flexible Lösungen zu erstellen, verlassen sich viele Entwickler weiterhin auf Standardschaltflächen, die direkt mit Ereignishandlern verknüpft sind. Dies ist wahrscheinlich auf Gewohnheit und mangelndes Bewusstsein für die Vorteile dieses Ansatzes zurückzuführen, was dazu führt, dass Schaltflächen eher konventioneller als einfache Auslöser für Aktionen verwendet werden.
Entschlossen, diese Situation zu ändern, habe ich die KoiCom-Bibliothek entwickelt, in der viele Komponenten bereits angepasst und erweitert wurden. Insbesondere die Schaltflächen in dieser Bibliothek folgen dem „Befehls“-Muster und übertragen die erforderlichen Daten und Befehle über Ereignisse. Dieser Ansatz erhöht die Modularität, Flexibilität und Wartbarkeit erheblich, eliminiert redundante Logik und vereinfacht die Befehlsverwaltung.
KoiCom-Dokumentation
KoiCom Github
Letztendlich hoffe ich, dass solche Lösungen Entwicklern dabei helfen werden, einen moderneren Ansatz für das Schnittstellendesign zu verfolgen, wodurch Anwendungen skalierbarer und einfacher zu warten sind.
Das obige ist der detaillierte Inhalt vonSchaltflächen der nächsten Generation: Implementierung des Befehlsmusters durch Webkomponenten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!