Benutzer:Rolf b/EventTarget
Es gibt viele Objekte inner- und außerhalb des DOM, die eine EventTarget-Schnittstelle anbieten. Wenn man komplexere Anwendungen erstellt, bietet es sich als Maßnahme zur Entkoppelung der Programmschichten an, auch für eigene Zwecke Events zu verwenden.
Beispielsweise ist es bei Verwendung des Entwurfsmusters Model-View-Controller so, dass ein Controller das Datenmodell kennt und den View, mit dem er es zur Anzeige gebracht hat. Darüber hinaus kennt auch der View das Datenmodell. Die umgekehrte Koppelung ist aber unerwünscht, weil ein View nicht für einen Controller und ein Modell nicht für einen View zugeschnitten sein soll. Das erschwert die Wiederverwendbarkeit.
Statt dessen stellen View und Modell für die Rückrichtung Events bereit, auf die man sich registrieren kann und womit View und Modell ihren Besitzer kontaktieren können. Die EventTarget-Schnittstelle des DOM ist ein gutes Werkzeug für diesen Zweck. Sie erlaubt es, dass ein Objekt Veränderungen seines Zustandes publiziert (publish) und eine beliebige Anzahl von anderen Objekten diese Publikation abonnieren (subscribe).
Wir wollen uns mit der Frage beschäftigen, wie man die EventTarget-Schnittstelle in eigenen Objekten bereitstellen kann. Der Gedanke, die Funktionalität von addEventListener, removeEventListener und dispatchEvent nachzubauen, ist keine gute Idee. Die Funktionalität ist da, also sollte man sie auch benutzen. Das war früher nicht so einfach, aber seit ein paar Jahren gibt es für diese Schnittstelle eine Konstruktorfunktion, von der man eigene Klassen ableiten kann:
class Person extends EventTarget {
constructor(name, vorname)
}
const p = new Person("Musterbach", "Erik");
p.addEventListener("change", function(changeEvent) { ... } );
Wenn Sie ihre Datenmodell-Objekte auf diese Weise bauen, können sich andere Objekte auf das change-Event registrieren und auf diese Weise feststellen, ob an dem beobachteten Objekt etwas verändert wurde. Beispielsweise könnte dann die Anzeige auf dem Bildschirm aktualisiert werden, oder es könnte registriert werden, dass dieses Objekt in die Datenbank zurückgeschrieben werden muss.
Voraussetzung dafür ist natürlich, dass Sie alle fachlichen Eigenschaften eines Person-Objekts mit Hilfe von Zugriffsmethoden bereitstellen, damit das change-Event beim Ändern einer Eigenschaft auch ausgelöst wird. Dafür ist es nützlich, noch eine abstrakte Klasse zwischenzuschalten, die die gemeinsame Infrastruktur für diese Aktionen bereitstellt.
class AbstractModel extends EventTarget {
constructor() {
super();
}
defineProperty(name, validator) {
Object.defineProperty(name, {
enumerable: true,
configurable: false,
get: function() { return this[name]; }
set: function(newValue) {
validator.
});
}
}
Eine frühe Idee war es, ein HTML-Element zu erzeugen (ohne es ins DOM zu stellen) und dieses Element als Publikationspunkt zu verwenden. Das hat den Vorteil, dass sich solche Elemente zu einer Node-Hierarchie zusammensetzen lassen und sogar Event-Bubbling möglich ist. Nachteilig ist, dass man an das DOM gebunden ist und dieses Verfahren beispielsweise in Node.js nicht verwendet werden kann.
{{Beispiel|titel=EventTarget mit internem DOM-Element|
{{BeispielCode|<source lang="javascript">