Heim > Artikel > Web-Frontend > Detaillierte grafische Erläuterung von Änderungen und Änderungserkennung in JavaScript-Frameworks
Detaillierte grafische Erklärung von Änderungen und Änderungserkennung in JavaScript-Frameworks
Ab 2015 haben Entwickler mehr Auswahlmöglichkeiten in Bezug auf JS-Frameworks. Neben Angular, Ember, React und Backbone sind mittlerweile zahlreiche Konkurrenten entstanden. Es gibt mittlerweile zu viele Frameworks zur Auswahl.
Jeder kann diese Frameworks aus verschiedenen Perspektiven vergleichen, aber ich denke, einer der interessantesten Unterschiede ist die Art und Weise, wie sie den Zustand verwalten. Insbesondere ist es sehr sinnvoll, darüber nachzudenken, wie diese Frameworks das tun, was sie tun, wenn sich der Zustand häufig ändert. Welche Methoden verwenden sie, um auf Änderungen in der Benutzeroberfläche zu reagieren?
Die Verwaltung des Anwendungsstatus und der Konsistenz der Benutzeroberfläche war lange Zeit eine Quelle der Komplexität in der UI-Entwicklung. Bisher haben wir verschiedene Möglichkeiten, damit umzugehen. In diesem Artikel werfen wir einen Blick auf einige davon: Embers Datenbindung, Angulars Dirty Checking, Reacts virtuelles DOM und seine Verbindung mit unveränderlichen Datenstrukturen.
Die grundlegende Aufgabe, über die wir sprechen werden, ist der interne Zustand des Programms und wie man ihn in sichtbare Elemente einfügt, die auf dem Bildschirm angezeigt werden. Sie nehmen eine Reihe von Objekten, Arrays, Zeichenfolgen und Zahlen und wandeln sie in eine Baumstruktur aus Text, Formularen, Links, Schaltflächen und Bildern um. In der Webentwicklung werden erstere häufig als JavaScript-Datenstrukturen und letztere als DOM ausgedrückt.
Wir nennen diesen Prozess oft „Rendering“. Sie können ihn sich als „Zuordnung“ Ihres Datenmodells in sichtbare Benutzeroberflächeninhalte vorstellen. Wenn Sie Daten mithilfe einer Vorlage rendern, erhalten Sie ein DOM (oder HTML) zur Darstellung der Daten.
Der Prozess selbst klingt recht einfach: Auch wenn die Zuordnung des Formulardatenmodells zur Benutzeroberfläche nicht trivial ist, handelt es sich um einen sehr unkomplizierten Konvertierungsprozess von der Eingabe zur Ausgabe.
Wenn wir erwähnen, dass sich Daten häufig ändern, werden die Dinge zu einer Herausforderung. Wenn der Benutzer mit der Benutzeroberfläche interagiert oder sich etwas in der Welt ändert, das die Daten aktualisiert, muss die Benutzeroberfläche diese Änderungen trotzdem widerspiegeln. Da der Neuaufbau des DOM-Baums außerdem ein teurer Vorgang ist und viel Geld kostet, sind wir bereit, so wenig Arbeit wie möglich zu leisten, um die Daten auf dem Bildschirm zu aktualisieren.
Im Vergleich zum einmaligen Rendern der Benutzeroberfläche gibt es ein schwierigeres Problem, da es sich um Statusaktualisierungen handelt. Auch hier ergeben sich verschiedene Szenarien.
„Keine Veränderung, das Universum ist unveränderlich“
Vor der großen JavaScript-Ära jeder Die Interaktion mit der Webseite löst eine Hin- und Her-Interaktion auf der Serverseite aus. Jeder Klick und jede Formularübermittlung führt dazu, dass die Webseite neu geladen wird. Der Server verarbeitet und antwortet Neue Seite, und der Browser lädt sie neu.
In diesem Fall muss das Frontend keinen Status verwalten. Jedes Mal, wenn etwas passiert, endet alles und der Browser unternimmt nichts. Unabhängig vom Status wird er vom Server verwaltet. Das Frontend besteht aus vom Server generiertem HTML und CSS und möglicherweise ein wenig Javascript.
Aus Front-End-Sicht ist dies eine sehr einfache Methode, und die Verarbeitung ist auch sehr langsam. Jede Interaktion bedeutet nicht nur ein erneutes Rendern der Benutzeroberfläche, sondern ist auch ein Remote-Interaktionsprozess, bei dem Daten an das Remote-Rechenzentrum und dann von der Remote-Schnittstelle an die Front-End-Schnittstelle zurückgegeben werden.
Heutzutage tun die meisten von uns das nicht mehr. Wir können den Status unserer Anwendung auf der Serverseite initialisieren und diesen Status dann im Frontend verwalten (ein großer Teil dieses isomorphen JavaScript-Artikels befasst sich damit), obwohl es immer noch einige Leute gibt, die diese komplexere Methode erfolgreich verwenden .
„Ich weiß nicht, wo ich neu zeichnen soll, bitte weisen Sie darauf hin“
JavaScript-Frameworks der ersten Generation , wie Backbone.js, Ext JS und Dojo, führten zum ersten Mal echte Datenmodelle in den Browser ein und ersetzten leichtgewichtige Skripte, die nur das DOM dekorierten. Dies bedeutet auch, dass Sie erstmals den Status im Browser ändern können. Der Inhalt des Datenmodells ändert sich, und Sie spiegeln diese Änderungen in der Benutzeroberfläche wider.
Obwohl diese Frameworks den UI-Code architektonisch vom Modell trennen, liegt es immer noch an Ihnen, die beiden zu synchronisieren. Wenn eine Änderung auftritt, können Sie eine Reihe von Ereignissen abrufen, es liegt jedoch an Ihnen, anzugeben, welcher Teil wie neu gerendert werden muss.
Die Leistung dieses Modells lässt Anwendungsentwicklern viel Raum zur Entwicklung. Da Sie steuern, wann welche Inhalte aktualisiert werden sollen, können Sie bei Bedarf eine Feinabstimmung vornehmen. Oft besteht ein Kompromiss zwischen der einfachen Neudarstellung großer Seitenbereiche und der Aktualisierung nur des kleinen Teils der Seite, der aktualisiert werden muss.
„Da ich das Modell und die Ansicht kontrolliere, weiß ich genau, welche neu gezeichnet werden sollten.“
Sein Die Fähigkeit, manuell anzuzeigen, welcher Zustand sich geändert hat und neu gerendert werden muss, ist die Hauptursache für Komplexität in der ersten Generation von JavaScript-Anwendungen. Eine große Anzahl von Frameworks ist darauf ausgelegt, diesen Teil des Problems zu beseitigen. Embe.js ist einer von ihnen.
Ember ähnelt Backbone. Wenn Änderungen auftreten, werden Ereignisse vom Modell ausgegeben. Der Unterschied besteht darin, dass Ember auch einige Funktionen für den Empfänger des Ereignisses bereitstellt. Sie können die Benutzeroberfläche an das Datenmodell binden, was bedeutet, dass ein Listener an die Benutzeroberfläche angehängt wird, um auf Änderungsereignisse zu warten. Dieser Listener weiß, was nach dem Empfang des Ereignisses aktualisiert werden soll.
Dadurch entsteht ein sehr effizienter Änderungsmechanismus: Durch die Einrichtung aller Bindungen zu Beginn werden die Kosten für die Synchronisierung später geringer. Wenn sich etwas ändert, ändern sich nur die Teile der Anwendung, die wirklich geändert werden müssen.
Bei diesem Ansatz besteht der größte Kompromiss darin, dass Ember über diese Änderungen informiert werden muss, wenn sich das Datenmodell ändert. Das bedeutet, dass Ihre Daten die spezifische API von Ember erben müssen und Sie Ihre Daten ändern müssen, um eine spezielle Set-Methode hinzuzufügen. Sie können foo.x=42 nicht verwenden, Sie müssen foo.set('x',42) usw. verwenden.
In Zukunft könnte dieser Ansatz von der Einführung von ECMAScript6 profitieren. Mithilfe der Bindungsmethode kann Ember ein allgemeines Objekt dekorieren, sodass der gesamte Code, der mit diesem Objekt interagiert, diese Satzkonvertierung nicht mehr verwenden muss.
„Ich weiß nicht, was sich geändert hat, ich habe nur alles überprüft, was aktualisiert werden musste“
Ähnlich wie Ember Angular Das Ziel besteht auch darin, das Problem zu lösen, dass nach Änderungen manuell neu gerendert werden muss. Es verwendet jedoch eine andere Methode.
Wenn Sie auf Ihren Angular-Vorlagencode verweisen, wie zum Beispiel diesen Ausdruck {{foo.x}}, lauscht Angular nicht nur auf diese Daten, sondern erstellt auch einen Beobachter für diesen Wert. Danach prüft Angular bei jeder Änderung in der Anwendung, ob sich der Wert im Beobachter seit dem letzten Mal geändert hat. Wenn es sich ändert, rendern Sie den Wert erneut auf der Benutzeroberfläche. Diese Art des Umgangs mit Inspektionsbeobachtern wird als Dirty Checking bezeichnet.
Der größte Vorteil dieser Erkennungsmethode besteht darin, dass Sie im Modell alles verwenden können, was Sie wollen. Angular hat diesbezüglich keine Einschränkungen – es ist ihm egal. Es ist nicht erforderlich, das Basisobjekt zu erben oder eine bestimmte API zu implementieren.
Der Nachteil besteht darin, dass das Datenmodell nicht über einen integrierten Detektor verfügt, der dem Framework mitteilt, was sich geändert hat, und das Framework keine Möglichkeit hat zu wissen, ob eine Änderung stattgefunden hat oder wo sie sich geändert hat. Dies bedeutet, dass Modelländerungen extern überprüft werden müssen, was Angular tut: Unabhängig von den Änderungen werden alle Beobachter ausgeführt: Klicken Sie auf Ereignisverarbeitung, HTTP-Antwortverarbeitung, Zeitüberschreitung usw., um eine Zusammenfassung zu generieren. Dies ist der verantwortliche Prozess zum Ausführen des Beobachters.
Jedes Mal alle Beobachter laufen zu lassen mag wie ein Performance-Albtraum klingen, ist aber tatsächlich blitzschnell. Dies liegt in der Regel daran, dass kein DOM-Zugriff erfolgt, bis eine Änderung tatsächlich erkannt wird, und der Aufwand für die Überprüfung von Referenzen in reinem JavaScript immer noch recht gering ist. Wenn Sie jedoch auf eine große Benutzeroberfläche stoßen oder häufig neu rendern müssen, sind zusätzliche Optimierungsmaßnahmen unerlässlich.
Wie Ember wird auch Angular von den kommenden Standards profitieren: EMACScript7 verfügt über die für Angular geeignete Methode Object.observe, die Ihnen eine native API zur Beobachtung von Objekteigenschaftenänderungen bietet. Obwohl dies nicht alle Anforderungen von Angular erfüllt, da Beobachter nicht nur einfache Objekteigenschaften beobachten.
Das kommende Angular2 wird auch einige interessante Updates zur Front-End-Update-Überprüfung bringen. Zu diesem Artikel wurde kürzlich ein Artikel von Victor Savkin veröffentlicht. Sie können sich auch ansehen, was Victor in ng-conf gesagt hat 🎜>
„Ich weiß nicht, was sich geändert hat, also werde ich alles rendern und sehen, was anders ist“
React hat eine Viele unterhaltsame Funktionen, von denen das virtuelle DOM das interessanteste ist.
React ähnelt Angular darin, dass es Sie nicht dazu zwingt, eine Modell-API zu verwenden, sondern Sie können alle Objekte und Datenstrukturen verwenden, die Sie für richtig halten. Wie hält es die Benutzeroberfläche nach Änderungen auf dem neuesten Stand?
Mit React kehren wir zu den Tagen des alten serverseitigen Renderings zurück, in denen wir alle Statusänderungen einfach ignorieren können: Jedes Mal, wenn sich irgendwo etwas ändert, wird die gesamte Benutzeroberfläche neu gezeichnet. Dies kann den UI-Code erheblich vereinfachen. Die Aufrechterhaltung des Status in React-Komponenten ist Ihnen egal. Genau wie beim serverseitigen Rendering rendern Sie einmal. Wenn eine Komponente geändert werden muss, wird sie erneut gerendert. Es gibt keinen Unterschied zwischen dem ersten Rendering und nachfolgenden Renderings mit aktualisierten Daten.
Das klingt äußerst ineffizient. Wenn React das nur tun würde, wäre es das. React verwendet jedoch eine spezielle Methode zum erneuten Rendern.
Wenn React UI rendert, wird es zunächst in ein virtuelles DOM gerendert. Es handelt sich nicht um ein tatsächliches DOM-Objekt, sondern um eine einfache, reine JavaScript-Objektstruktur, die einfache Objekte und Arrays enthält, um die Realität auszudrücken. Es wird einen speziellen Prozess geben, um dieses virtuelle DOM zu erhalten und echte DOM-Elemente zu erstellen, die auf dem Bildschirm angezeigt werden können.
Wenn es dann eine Änderung gibt, wird aus der Änderung ein neues virtuelles DOM generiert. Dieses neue virtuelle DOM spiegelt den neuen Zustand des Datenmodells wider. React verfügt jetzt über zwei virtuelle DOMs: neu und alt. Es verwendet einen Differenzvergleichsalgorithmus für die beiden virtuellen DOMs, um den Änderungssatz zu erhalten. Diese Änderungen, und nur diese Änderungen, werden auf das echte DOM angewendet: Neue Elemente werden hinzugefügt, Attributwerte von Elementen werden geändert usw.
Ein sehr großer Vorteil der Verwendung von React, oder zumindest einer der Vorteile, besteht darin, dass Sie Änderungen nicht verfolgen müssen. Egal wann oder wo sich etwas an den neuen Ergebnissen ändert, Sie müssen lediglich die gesamte Benutzeroberfläche neu rendern. Die Differenzprüfungsmethode von Virtual DOM erledigt dies automatisch für Sie und reduziert so viele teure DOM-Vorgänge.
„Ich kann klar wissen, dass sich diese Dinge nicht geändert haben“
Obwohl die virtuelle DOM-Technologie von React sehr gut war schneller, aber wenn die Seite, die Sie rendern möchten, groß oder sehr häufig ist (mehr als 60 Mal pro Sekunde), entsteht immer noch ein Leistungsengpass.
Es führt wirklich kein Weg daran vorbei, das gesamte (virtuelle und reale) DOM neu zu rendern, es sei denn, Sie nehmen beim Ändern des Datenmodells einige spezielle Steuerelemente vor, wie es Ember tut.
Eine Möglichkeit, Änderungen zu kontrollieren, sind unveränderliche, persistente Datenstrukturen.
Sie scheinen gut mit den virtuellen DOM-Methoden von React zu funktionieren, wie David Nolens Arbeit mit der Om-Bibliothek zeigt, die auf React und ClojureScript basiert.
Das Sprichwort über unveränderliche Datenstrukturen lautet: Wie der Name schon sagt, können Sie ein Objekt nicht ändern, sondern nur eine neue Version davon erstellen: Wenn Sie die Eigenschaften eines Objekts ändern möchten, können Sie dies nicht Wenn Sie es ändern, können Sie nur ein neues Objekt erstellen und es auf diese neue Eigenschaft festlegen. Aufgrund der Funktionsweise persistenter Daten funktioniert dies in der Praxis besser, als es sich anhört.
Wenn React-Komponentenzustände aus unveränderlichen Daten bestehen, sieht die Änderungsprüfung wie folgt aus: Wenn Sie eine Komponente erneut rendern, zeigt der Zustand der Komponente immer noch auf den Zustand an, als Sie sie das letzte Mal mit denselben Daten gerendert haben Struktur können Sie dieses Rendering überspringen und weiterhin das letzte virtuelle DOM dieser Komponente sowie die gesamte interne Komponente mit dieser unveränderten Komponente als Verzweigungsknoten verwenden. Es besteht derzeit keine Notwendigkeit, weitere Tests durchzuführen, da keine Statusänderungen vorliegen.
Genau wie bei Ember erlauben Ihnen Bibliotheken wie Om nicht, alte Javascript-Objektdiagramme in Ihren Daten zu verwenden. Sie können Ihr Modell nur mit unveränderlichen Datenstrukturen von Grund auf aufbauen. Ich würde behaupten, dass der Unterschied darin besteht, dass Sie es dieses Mal nicht tun müssen, um die Anforderungen des Frameworks zu erfüllen. Sie tun dies einfach, weil es eine bessere Möglichkeit ist, den Anwendungsstatus zu verwalten. Der Vorteil der Verwendung unveränderlicher Datenstrukturen besteht nicht in der Verbesserung der Rendering-Leistung, sondern in der Vereinfachung Ihrer Anwendungsarchitektur.
Om und ClojureScript sind auch nützlich bei der Kombination von React und unveränderlichen Datenstrukturen, aber sie sind nicht unbedingt erforderlich. Es könnte ausreichen, nur reines React und eine Bibliothek wie Immutable-js von Facebook zu verwenden. Lee Byron, der Autor dieser Bibliothek, gab auf der React.js Conf eine großartige Einführung in dieses Thema.
Ich empfehle Ihnen, einen Blick auf Rich Hickeys persistente Datenstruktur und Referenzverwaltung zu werfen. Dies ist auch eine Einführung in die Methoden der Zustandsverwaltung.
Ich verwende seit einiger Zeit unveränderliche Datenstrukturen, um Poesie zu produzieren. Obwohl ich nicht davon ausgehen kann, dass es in der Front-End-UI-Architektur verwendet wird. Aber es scheint, dass dies geschieht, und das Angular-Team arbeitet auch daran, Unterstützung für diese Inhalte hinzuzufügen.
Änderungserkennung ist ein zentrales Thema in der UI-Entwicklung, und verschiedene JavaScript-Frameworks verwenden ihre eigenen Methoden, um unterschiedliche Lösungen bereitzustellen.
EmberJS kann Änderungen erkennen, wenn sie auftreten, da es die Datenmodell-API steuert. Wenn Sie die API aufrufen, um Datenänderungen vorzunehmen, wird das entsprechende Ereignis ausgelöst.
Angular.js erkennt Änderungen, nachdem die Änderungen aufgetreten sind. Es führt die auf der Benutzeroberfläche registrierte Datenbindung erneut aus und prüft dann, ob sich Werte geändert haben.
Pure React erkennt Datenänderungen, indem es die gesamte Benutzeroberfläche in einem neuen virtuellen DOM neu rendert und es dann mit dem alten virtuellen DOM vergleicht. Finden Sie heraus, was sich geändert hat, und senden Sie es als Revision an das echte DOM.
React- und unveränderliche Datenstrukturen können als erweiterte Version reiner React-Lösungen verwendet werden, die den Komponentenbaum schnell als unveränderten Zustand markieren können, da Zustandsänderungen innerhalb von React-Komponenten nicht zulässig sind. Das Verbieten von Änderungen am internen Status erfolgt nicht aus Leistungsgründen, sondern weil sich dies positiv auf die Architektur Ihrer Anwendung auswirkt.
Übersetzer: Li Bingchen, arbeitet in der HP-Softwareentwicklungsabteilung, mehr als 10 Jahre Erfahrung in der JAVA-Produktentwicklung, vertraut mit C#, Python, Nodejs. Er verfügt über umfangreiche Erfahrung im Bereich Internet-E-Commerce-Plattformen sowie in der Entwicklung und Verwaltung von Unternehmenssoftware. Meine aktuellen Interessen liegen in der Frontend-Entwicklung und der Anwendung statistischer Datenanalysen in Finanzdienstleistungen.
Das obige ist der detaillierte Inhalt vonDetaillierte grafische Erläuterung von Änderungen und Änderungserkennung in JavaScript-Frameworks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!