Detaillierte Erläuterung des virtuellen DOM in der Vue-Quellcodeanalyse

Detaillierte Erläuterung des virtuellen DOM in der Vue-Quellcodeanalyse

Warum brauchen wir virtuellen Dom?

Virtual DOM wurde entwickelt, um Leistungsprobleme von Browsern zu lösen. Wenn beispielsweise in einem Vorgang 10 DOM-Updates vorhanden sind, führt der virtuelle DOM den DOM nicht sofort aus, sondern speichert den DOM-Diff-Inhalt dieser 10 Updates in einem lokalen JS-Objekt und hängt dieses JS-Objekt schließlich auf einmal an den DOM-Baum an. Anschließend werden die nachfolgenden Vorgänge ausgeführt, wodurch viele unnötige Berechnungen vermieden werden. Vereinfacht ausgedrückt kann Virtual DOM als einfaches JS-Objekt verstanden werden und enthält mindestens drei Attribute: Tag-Name (Tag), Attribute (Attrs) und untergeordnete Elementobjekte (Children).

  • ----- Elementknoten: Der Elementknoten ähnelt eher dem echten DOM-Knoten, den wir normalerweise sehen. Er verfügt über ein Tag-Attribut, das das Nomen der Knotenbezeichnung beschreibt, ein Datenattribut, das die Knoteneigenschaften wie Klasse und Attribute beschreibt, und ein Kinderattribut, das die enthaltenen Informationen zum untergeordneten Knoten beschreibt. Da die in Elementknoten enthaltenen Situationen relativ komplex sind, werden sie nicht wie die ersten drei Knotentypen direkt in den Quellcode geschrieben.
  • Die Rolle von VNode: Nutzen Sie die Rechenleistung von js im Austausch für die Leistung, die durch den Betrieb des realen DOM verbraucht wird.
  • ----- Welche Rolle spielt VNode im gesamten virtuellen DOM-Prozess von Vue? Tatsächlich ist die Rolle des VNode ziemlich wichtig. Bevor wir die Ansicht rendern, kompilieren wir die geschriebene Vorlage in VNode und speichern sie im Cache. Wenn die Seite aufgrund von Datenänderungen neu gerendert werden muss, vergleichen wir den nach den Datenänderungen generierten VNode mit dem beim letzten Mal im Cache gespeicherten VNode, um den Unterschied festzustellen. Dann ist der reale DOM-Knoten, der dem unterschiedlichen VNode entspricht, der Knoten, der erneut gerendert werden muss. Schließlich wird der mit dem Unterschied erstellte DOM-Knoten in die Ansicht eingefügt und schließlich wird eine Ansichtsaktualisierung abgeschlossen. Es dient zum Generieren virtueller DOM-Knoten, die dem realen DOM vor und nach der Datenänderung entsprechen

Warum brauchen wir virtuellen DOM?

----- Es geht darum, die Rechenleistung von JS gegen die Leistung auszutauschen, die durch den Betrieb des realen DOM verbraucht wird. Vue instanziiert verschiedene Typen virtueller DOM-Knoten über die VNode-Klasse und lernt die Unterschiede in den von verschiedenen Knotentypen generierten Attributen. Die sogenannten verschiedenen Knotentypen sind im Wesentlichen gleich, sie sind alle Instanzen der VNode-Klasse, aber die während der Instanziierung übergebenen Parameter sind unterschiedlich.
Mit den Datenänderungen vor und nach dem VNode können wir anschließend DOM-Diff ausführen, um die Unterschiede zu ermitteln, und schließlich nur die Ansichten mit Unterschieden aktualisieren, um das Ziel zu erreichen, den realen DOM so wenig wie möglich zu betreiben, um Leistung zu sparen.

----- Und durch das Herausfinden der DOM-Knoten mit unterschiedlichen Aktualisierungen wurde das Ziel erreicht, die Ansicht mit möglichst wenig Aufwand am realen DOM zu aktualisieren. Der Prozess des Vergleichens der alten und neuen VNodes und des Findens der Unterschiede ist der sogenannte DOM-Diff-Prozess. Der DOM-Diff-Algorithmus ist der Kern des gesamten virtuellen DOM.

Pflaster

In Vue wird der DOM-Diff-Prozess als Patch-Prozess bezeichnet. Patch bedeutet Patch, was eine Idee bedeutet: Der sogenannte alte VNode (odlNode) ist der entsprechende virtuelle DOM-Knoten vor der Datenänderung, und der neue NVode ist der virtuelle DOM-Knoten, der der nach der Datenänderung zu rendernden Ansicht entspricht. Daher müssen wir den generierten neuen VNode als Benchmark verwenden, um den alten oldVNode zu vergleichen. Wenn sich auf dem neuen VNode ein Knoten befindet, aber nicht auf dem alten oldVNode, fügen Sie ihn dem alten oldVNode hinzu. Wenn sich auf dem neuen VNode ein Knoten befindet, der sich jedoch nicht auf dem alten oldVNode befindet, entfernen Sie ihn vom alten oldVNode. Wenn sowohl der alte als auch der neue VNode-Knoten vorhanden sind, wird der neue VNode als Referenz verwendet und der alte oldVNode wird aktualisiert, sodass der neue und der alte VNode-Knoten identisch sind.

Bei dem gesamten Patch geht es um das Erstellen von Knoten: Neue VNodes sind vorhanden, alte jedoch nicht. Erstellen Sie es im alten oldVNode

Einen Knoten löschen: Wenn der Knoten im neuen VNode nicht vorhanden ist, im alten VNode jedoch vorhanden ist, löschen Sie ihn aus dem alten VNode.

Knoten aktualisieren: Wenn sowohl der neue als auch der alte verfügbar sind, wird der neue VNode als Referenz verwendet und der alte oldVNode wird aktualisiert.

Untergeordnete Knoten aktualisieren

/* 
    Um zwei untergeordnete Knoten-Arrays zu vergleichen, müssen Sie die äußere Schleife newChildren und die innere Schleife oldCHildren-Array durchlaufen. Für jeden untergeordneten Knoten im äußeren newChildren-Array suchen Sie im inneren oldChildren-Array nach einem identischen untergeordneten Knoten*/
für (lass i = 0; i < newChildred.length; i++) {
    const neuesKind = neueKinder[i]
    für (let j = 0; j < oldChildren.length; j++) {
        const altesKind = alteKinder[i]
        wenn (neuesKind === altesKind) {
            // ...
        }
    }
}

Dann treten bei dem obigen Prozess die folgenden vier Situationen auf

  1. Untergeordnete Knoten erstellen. Wenn ein untergeordneter Knoten in newChildren denselben untergeordneten Knoten in oldChildren nicht finden kann, bedeutet dies, dass der untergeordnete Knoten in newChildren zuvor nicht vorhanden war und dieses Mal hinzugefügt werden muss. Erstellen Sie daher den untergeordneten Knoten.
  2. Untergeordnete Knoten löschen. Wenn nach dem Durchlaufen aller untergeordneten Knoten in „newChildren“ immer noch unbearbeitete untergeordnete Knoten in „oldChildren“ vorhanden sind, bedeutet dies, dass die unbearbeiteten untergeordneten Knoten verworfen werden müssen. Löschen Sie diese Knoten daher.
  3. Untergeordnete Knoten verschieben. Wenn ein untergeordneter Knoten in newChildren denselben untergeordneten Knoten in oldChildren findet, die Position jedoch unterschiedlich ist, bedeutet dies, dass die Position des untergeordneten Knotens angepasst werden muss. Passen Sie dann basierend auf der Position von untergeordnetem Knoten 1 in newChildren die Position des Knotens in oldChildren so an, dass er mit der Position in newChildren übereinstimmt.
  4. Knoten aktualisieren: Wenn ein untergeordneter Knoten in newChildren denselben untergeordneten Knoten in oldChildren findet und die Position dieselbe ist, aktualisieren Sie den Knoten in oldChildren, um ihn mit dem Knoten in newChildren identisch zu machen.

Wir haben wiederholt betont, dass die Aktualisierung von Knoten auf dem neuen Vnode basieren sollte und dass dann der alte oldVnode so betrieben werden sollte, dass der alte oldVNode derselbe ist wie der neue VNode.

Das Update gliedert sich in drei Teile:

Wenn VNode und oldVNode beide statische Knoten sind,

Wie bereits erwähnt, haben statische Knoten keinen Bezug zu Datenänderungen. Wenn es sich also ausschließlich um statische Knoten handelt, werden sie ohne Verarbeitung direkt übersprungen.

Wenn der VNode ein Textknoten ist

Wenn VNode ein Textknoten ist, was bedeutet, dass dieser Knoten nur einfachen Text enthält, müssen Sie nur prüfen, ob oldVNode auch ein Textknoten ist. Wenn dies der Fall ist, vergleichen Sie, ob die beiden Texte unterschiedlich sind. Wenn nicht, ändern Sie den Text in oldVNode so, dass er mit dem Text in VNode übereinstimmt. Wenn oldVNode kein Textknoten ist, rufen Sie unabhängig davon, was es ist, direkt die Methode setTextNode auf, um es in einen Textknoten zu ändern, und der Textinhalt ist derselbe wie bei VNode.

Wenn VNode ein Elementknoten ist, wird er weiter in die folgenden zwei Fälle unterteilt

  1. Der Knoten enthält untergeordnete Knoten. Daher müssen wir zu diesem Zeitpunkt prüfen, ob der alte Knoten untergeordnete Knoten enthält. Wenn der alte Knoten untergeordnete Knoten enthält, müssen wir die untergeordneten Knoten rekursiv vergleichen und aktualisieren.
  2. Wenn der alte Knoten keine untergeordneten Knoten enthält, kann es sich bei dem alten Knoten um einen leeren Knoten oder einen Textknoten handeln.
  3. Wenn der alte Knoten ein leerer Knoten ist, erstellen Sie eine Kopie des untergeordneten Knotens im neuen Knoten und fügen Sie sie in den alten Knoten ein.
  4. Wenn der alte Knoten ein Textknoten ist, löschen Sie den Text, erstellen Sie eine Kopie des untergeordneten Knotens im neuen Knoten und fügen Sie sie in den alten Knoten ein.
  5. Der Knoten enthält keine untergeordneten Knoten. Wenn der Knoten keine untergeordneten Knoten enthält und kein Textknoten ist, bedeutet dies, dass der Knoten ein leerer Knoten ist. Das lässt sich leicht handhaben. Egal, was vorher im alten Knoten war, löschen Sie es einfach.
// Knoten aktualisieren Funktion patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly) {
    // Sind vnode und oldVnode genau gleich? Wenn ja, beenden Sie das Programm if (oldVnode === vnode) {
        zurückkehren
    }
    const elm = vnode.elm = alterVnode.elm
    //Sind vnode und oldVnode beides statische Knoten? Wenn ja, beenden Sie das Programm if (isTrue(vnode.isStatic) && isTrue(vnode.isStatic) && vnode.key === oldVnode.key && (isTrue(vnode.isCloned) || isTrue(vnode.isOnce))) {
        zurückkehren
    }
    const oldCh = oldVnode.children
    const ch = vnode.children
    // vnode hat Textattribut, wenn nicht if (isUndef(vnode.text)) {
        wenn (isDef(alterCh) und isDef(ch)) {
            // Wenn beide vorhanden sind, ermitteln Sie, ob die untergeordneten Knoten gleich sind. Wenn sie unterschiedlich sind, aktualisieren Sie die untergeordneten Knoten, wenn (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQueue, removeOnly)
        }
        // Wenn nur die untergeordneten Knoten von vnode existieren, sonst wenn (isDef(ch)) {
            /**
             * Bestimmen Sie, ob oldVnode Text hat. * Wenn nicht, fügen Sie die untergeordneten Knoten von Vnode zum realen DOM hinzu. * Wenn ja, löschen Sie den Text im DOM und fügen Sie die untergeordneten Knoten von Vnode zum realen DOM hinzu. * */
            wenn (isDef(alterVnode.text)) nodeOps.setTextContext(elm, '')
            addVnodes(elm, null, ch, 0, ch.length - 1, eingefügteVnodeQueue)
        }
        // Wenn nur der untergeordnete Knoten von oldnode existiert, sonst wenn (isDef(oldCh)) {
            // Alle untergeordneten Knoten im DOM löschen removeVnodes(elm, oldCh, 0, oldCh.length - 1)
        }
        // Wenn vnode und oldnode keine Kindknoten haben, oldnode aber Text hat, sonst wenn (isDef(oldVnode.text)) {
            nodeOps.setTextContext(ulme, '')
        }
        // Die beiden obigen Urteile können in einem Satz zusammengefasst werden: Wenn im vnode weder Text noch untergeordnete Knoten vorhanden sind, dann lösche alles, was sich im entsprechenden alten Knoten befindet} else if (oldVnode.text !== vnode.text) {
        nodeOps.setTextContext(elm, vnode.text)
    }
}

Oben haben wir etwas über den Patch von Vue gelernt, bei dem es sich um den DOM-DIFF-Algorithmus handelt, und wir wissen, dass im Patch-Prozess grundsätzlich drei Dinge zu tun sind, nämlich Knoten erstellen, Knoten löschen und Knoten aktualisieren. Das Erstellen und Löschen von Knoten ist relativ einfach, das Aktualisieren von Knoten erfordert jedoch eine komplexere Logik, da verschiedene mögliche Situationen behandelt werden müssen. Während des Aktualisierungsvorgangs können alle neun Vnodes untergeordnete Knoten enthalten. Es wird eine zusätzliche Logik zum Vergleichen und Aktualisieren der untergeordneten Knoten geben. In diesem Artikel erfahren Sie, wie Sie untergeordnete Knoten in Vue vergleichen.

Untergeordnete Knoten aktualisieren

Wenn der neue Vnode und der alte Vnode beide Elementknoten sind und untergeordnete Knoten enthalten, ist das chidlren-Attribut der beiden Knoten-VNode-Instanzen das enthaltene untergeordnete Knoten-Array. Vergleichen Sie die beiden untergeordneten Knoten durch Schleifen, die äußere Schleife des newChildren-Arrays, die innere Schleife des oldChildren-Arrays, jede Schleife für einen untergeordneten Knoten im äußeren newChildren-Array, gehen Sie zum inneren oldChildren-Array, um zu sehen, ob es denselben untergeordneten Knoten gibt

. Untergeordnete Knoten erstellen

Die Position, an der untergeordnete Knoten erstellt werden, sollte vor allen unverarbeiteten Knoten liegen, nicht nach allen verarbeiteten Knoten. Denn wenn der untergeordnete Knoten nach dem verarbeiteten Knoten eingefügt wird und später ein neuer Knoten eingefügt werden soll, werden die neu hinzugefügten untergeordneten Knoten durcheinander gebracht.

. Untergeordnete Knoten verschieben

Alle unbearbeiteten Knoten sind die Standorte, zu denen wir wechseln möchten.

Optimieren Sie die Aktualisierung untergeordneter Knoten:

Wir haben bereits erwähnt, dass Vue, wenn der neue VNode und der alte VNode beide Elementknoten sind und beide untergeordnete Knoten enthalten, zuerst das newChildren-Array in der äußeren Schicht und dann das oldChildren-Array in der inneren Schicht durchläuft. Bei jeder Schleife eines untergeordneten Knotens im äußeren newChildren-Array wird im inneren oldChildren-Array nachgesehen, ob ein identischer untergeordneter Knoten vorhanden ist, und schließlich je nach Situation unterschiedliche Vorgänge ausgeführt. Es gibt noch Bereiche, die optimiert werden können. Wenn beispielsweise eine große Anzahl untergeordneter Knoten vorhanden ist, wird die zeitliche Komplexität des Schleifenalgorithmus sehr groß, was einer Leistungsverbesserung nicht förderlich ist.

Verfahren:

  1. Vergleichen Sie zunächst den ersten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im newChildren-Array mit dem ersten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im oldChildren-Array. Wenn sie gleich sind, fahren Sie direkt mit dem Knotenaktualisierungsvorgang fort.
  2. Wenn sie unterschiedlich sind, vergleichen Sie den letzten Knoten aller unverarbeiteten untergeordneten Knoten im newChildren-Array mit dem letzten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im oldChildren-Array. Wenn sie gleich sind, geben Sie direkt den Knotenaktualisierungsvorgang ein.
  3. Wenn sie unterschiedlich sind, vergleichen Sie den letzten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im newChildren-Array mit dem ersten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im oldChildren-Array. Wenn sie gleich sind, führen Sie direkt den Knotenaktualisierungsvorgang aus. Verschieben Sie nach der Aktualisierung den Knoten im oldChildren-Array an dieselbe Position wie den Knoten im newChildren-Array. Wenn sie unterschiedlich sind,
  4. Vergleichen Sie dann den ersten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im newChildren-Array mit dem letzten untergeordneten Knoten aller unverarbeiteten untergeordneten Knoten im oldChildren-Array. Wenn sie gleich sind, führen Sie direkt den Knotenaktualisierungsvorgang aus. Verschieben Sie nach der Aktualisierung den Knoten im oldChildren-Array an dieselbe Position wie den Knoten im newChildren-Array.
  5. Wenn die letzten vier Fälle ausprobiert wurden und immer noch unterschiedlich sind, suchen Sie auf die gleiche Weise wie zuvor nach dem Knoten.
    Um die Leistungsprobleme zu vermeiden, die durch die große Datenmenge und die erhöhte Zeitkomplexität der Doppelschleife verursacht werden, vergleicht Vue vier spezielle Positionen im untergeordneten Knotenarray, nämlich: neue Vorderseite und alte Vorderseite, neue Rückseite und alte Rückseite, neue Rückseite und alte Vorderseite, neue Vorderseite und alte Rückseite

In den vorherigen Artikeln haben wir den virtuellen DOM in Vue und den Patch-Prozess (DOM-Diff) des virtuellen DOM vorgestellt. Die notwendige Voraussetzung für die Existenz des virtuellen DOM ist der vorhandene VNode. Woher kommt also der VNode? Das Kompilieren der vom Benutzer geschriebenen Vorlage erzeugt einen VNode

Vorlagenzusammenstellung:

Was ist Vorlagenkompilierung: Kompilieren Sie den Inhalt ähnlich dem nativen HTML, das im Vorlagen-Tag des Benutzers geschrieben ist, suchen Sie den Inhalt des nativen HTML und suchen Sie dann das nicht native HTML. Nach einer Reihe logischer Verarbeitungen wird eine Rendering-Funktion generiert. Dieser Prozess der Rendering-Funktion wird als Vorlagenkompilierungsprozess bezeichnet. Die Renderfunktion generiert einen VNode aus dem Vorlageninhalt

Der gesamte Rendering-Prozess, der sogenannte Rendering-Prozess, besteht darin, die vom Benutzer geschriebene Vorlage, die nativem HTML ähnelt, durch eine Reihe von Prozessen in der Ansicht widerzuspiegeln. Dieser Prozess wurde oben erwähnt.

Abstrakter Syntaxbaum AST:

  • Die vom Benutzer im Vorlagentag geschriebene Vorlage ist eine Reihe von Zeichenfolgen für Vue. Wie kann man also diese Reihe von Zeichenfolgen analysieren und daraus die Tags, Attribute, Variableninterpolationen und andere gültige Informationen des Elements extrahieren? Dazu ist die Hilfe eines sogenannten abstrakten Syntaxbaums erforderlich.
    Ein abstrakter Syntaxbaum, auch Syntaxbaum genannt, ist eine abstrakte Darstellung der Syntaxstruktur eines Quellcodes. Er stellt die Syntaxstruktur einer Programmiersprache in Form eines Baums dar. Jeder Knoten im Baum stellt eine Struktur im Quellcode dar. Der Grund, warum die Syntax abstrakt ist, liegt darin, dass die Syntax hier nicht jede Struktur darstellt, die in der realen Syntax vorkommt. Beispielsweise sind verschachtelte Klammern in der Baumstruktur impliziert und werden nicht in Form eines Knotens i dargestellt.

Spezifischer Prozess:

  • Nachdem wir eine Reihe von Zeichenfolgenvorlagen in abstrakte Syntaxbäume (ASTs) analysiert haben, können wir verschiedene Operationen an ihnen durchführen. Nach der Verarbeitung wird der AST verwendet, um die Renderfunktion zu generieren. Die spezifischen drei Prozesse können in die folgenden drei Phasen unterteilt werden:

Phase der Vorlagenanalyse: Analysieren Sie eine Reihe von Vorlagenzeichenfolgen mithilfe regulärer Ausdrücke in einen abstrakten Syntaxbaum (AST).

Optimierungsphase: AST kompilieren, statische Knoten finden und markieren

Codegenerierungsphase: Konvertieren Sie AST in eine Rendering-Funktion

Nur mit der Vorlagenkompilierung können wir einen virtuellen DOM und anschließende Ansichtsaktualisierungen haben.

Zusammenfassen

Dies ist das Ende dieses Artikels über die Vue-Quellcodeanalyse und den virtuellen DOM. Weitere relevante Inhalte zum virtuellen Vue-DOM finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Dieser Artikel hilft Ihnen, den virtuellen Dom- und Diff-Algorithmus von Vue zu verstehen
  • Das Prinzip des virtuellen DOM von Vue
  • Über das Vue Virtual Dom-Problem
  • Vue Virtual DOM – Schnellstart
  • Zusammenfassung des Verständnisses des virtuellen DOM in Vue
  • Konvertierung von virtuellem Dom in reales Dom mit Vue
  • Zusammenfassung der virtuellen DOM-Wissenspunkte in Vue

<<:  Lösung für den Fehler 2059 beim Verbinden von Navicat mit MySQL

>>:  IIS7~IIS8.5 Löschen oder Ändern des Serverprotokollheaders Server

Artikel empfehlen

Analyse von MySQL-Parallelitätsproblemen und -Lösungen

Inhaltsverzeichnis 1. Hintergrund 2. Langsame Abf...

Detaillierte Erläuterung der Einführung in die JavaScript-Funktion

Inhaltsverzeichnis Funktionseinführung Funktion E...

Detaillierte Erklärung der neuen Funktionen von ES9: Asynchrone Iteration

Inhaltsverzeichnis Asynchrones Durchlaufen Asynch...

Detaillierte Erklärung zur Verwendung von Docker-Compose-Befehlen

Sie können Docker-Container auf verschiedene Arte...

Implementierung der Docker-Bereitstellung des SQL Server 2019 Always On-Clusters

Inhaltsverzeichnis Docker-Bereitstellung Always o...

Analyse und Behandlung von Bildlaufleisten in HTML und eingebettetem Flash

Bei der Entwicklung begegnen wir häufig dieser Sit...

Lösung zur Definition der Mindestspannweite hat keine Auswirkung

Das Span-Tag wird häufig beim Erstellen von HTML-W...

So stellen Sie den Node.js-Dienst mithilfe von Dockerfile bereit

Dockerfile initialisieren Angenommen, unser Proje...

Implementierung der MySQL Master-Slave-Statusprüfung

1. Überprüfen Sie den Synchronisierungsstatus der...

Vergleichende Analyse von MySQL Binlog-Protokollverarbeitungstools

Inhaltsverzeichnis Kanal Maxwell Datenbus Datenüb...

HTML+CSS-Implementierungscode für abgerundete Rechtecke

Mir war langweilig und plötzlich fiel mir die Impl...

So zeigen Sie JSON-Daten auf einer HTML-Seite an und formatieren sie

JSON-Daten werden auf der HTML-Seite angezeigt un...