Vue Virtual DOM – Schnellstart

Vue Virtual DOM – Schnellstart

Virtueller DOM

Was ist virtueller Dom

DOM ist ein Dokumentobjektmodell, das Dokumente in Form eines Knotenbaums darstellt.

Virtueller DOM ist kein echter DOM. Es handelt sich vielmehr um ein Javascript-Objekt.

Ein normaler DOM-Knoten wird in HTML wie folgt dargestellt:

<div Klasse='Test-ID'>
    <p>Hallo</p>
    <p>Willkommen</p>
</div>

Im virtuellen DOM sieht es folgendermaßen aus:

{
    Tag: 'div',
    Attribute:
        Klasse: ['Test-ID']
    },
    Kinder:[
        // p-Element // p-Element]
}

Zum besseren Verständnis können wir den virtuellen Dom in zwei Teile aufteilen: virtuell + Dom.

  • Virtuell: bedeutet, dass der virtuelle DOM kein echter DOM, sondern ein JavaScript-Objekt ist;
  • dom: Gibt an, dass der virtuelle Dom das Dokument in einer knotenbaumähnlichen Form darstellen kann.

Die Rolle des virtuellen Doms

Die aktuellen Mainstream-Frameworks sind alle Frameworks für deklarative DOM-Operationen. Wir müssen nur die Zuordnungsbeziehung zwischen dem Status und dem DOM beschreiben. Das Framework hilft uns dabei, den Status in die Ansicht (das echte DOM) zu konvertieren.

Der einfachste Ansatz besteht darin, den Status in einer Ansicht darzustellen und die gesamte Ansicht bei jeder Aktualisierung des Status zu aktualisieren.

Die Leistung dieses Ansatzes kann man sich vorstellen. Eine bessere Idee ist: Wenn sich der Status ändert, werden nur die mit dem Status verbundenen DOM-Knoten aktualisiert. Virtueller DOM ist nur eine Möglichkeit, diese Idee umzusetzen.

Konkrete Schritte:

  • Status -> Realer Dom (zunächst)
  • Status -> Virtueller DOM -> Realer DOM (unter Verwendung des virtuellen DOM)

Wenn sich der Status ändert, wird ein neuer virtueller DOM generiert, der vorherige mit diesem verglichen, die Teile gefunden, die aktualisiert werden müssen, und der reale DOM wird aktualisiert.

Virtueller DOM in Vue

Das reale Dom besteht aus Knoten (Node) und das virtuelle Dom besteht aus virtuellen Knoten (vNode).

Der virtuelle DOM erledigt in Vue hauptsächlich zwei Aufgaben:

  • Stellt virtuelle Knoten (vNode) bereit, die den realen Knoten (Node) entsprechen
  • Vergleichen Sie den neuen virtuellen Knoten mit dem alten virtuellen Knoten, finden Sie die Unterschiede und aktualisieren Sie dann die Ansicht

„Virtual DOM“ ist unser Name für den gesamten VNode-Baum, der vom Vue-Komponentenbaum erstellt wird – offizielle Vue-Website

vNode

Was ist vNode

Wie oben erwähnt, entspricht vNode (virtueller Knoten) dem realen Knoten (Node).

vNode kann als Knotenbeschreibungsobjekt verstanden werden. Beschreibt, wie man tatsächliche DOM-Knoten erstellt

Es gibt eine vNode-Klasse in vue.js. Damit können verschiedene Typen von vNode-Instanzen erstellt werden. Verschiedene Typen von vNodes entsprechen verschiedenen Typen von DOM-Elementen. Der Code lautet wie folgt:

exportiere Standardklasse VNode {
   Konstruktor (
    Tag?: Zeichenfolge,
    Daten?: VNodeData,
    Kinder?: ?Array<VNode>,
    Text?: Zeichenfolge,
    Ulme?: Knoten,
    Kontext?: Komponente,
    Komponentenoptionen?: VNodeComponentOptions,
    asyncFactory?: Funktion
  ) {
    this.tag = Tag
    this.data = Daten
    this.children = Kinder
    dieser.text = Text
    diese.ulme = Ulme
    this.ns = undefiniert
    this.context = Kontext
    this.fnContext = nicht definiert
    this.fnOptions = nicht definiert
    this.fnScopeId = nicht definiert
    dieser.Schlüssel = Daten && Daten.Schlüssel
    this.componentOptions = Komponentenoptionen
    this.componentInstance = nicht definiert
    this.parent = undefiniert
    this.raw = falsch
    this.isStatic = falsch
    this.isRootInsert = true
    this.isComment = false
    this.isCloned = falsch
    this.isOnce = falsch
    this.asyncFactory = asyncFactory
    this.asyncMeta = nicht definiert
    this.isAsyncPlaceholder = falsch
  }

  hol Kind (): Komponente | void {
    gib diese.Komponenteninstanz zurück
  }
}

Aus dem Code lässt sich leicht erkennen, dass die von der vNode-Klasse erstellte Instanz im Wesentlichen ein gewöhnliches JavaScript-Objekt ist.

Typ des vNode

Wir haben bereits vorgestellt, dass mit der vNode-Klasse verschiedene Arten von vNodes erstellt werden können. Verschiedene vNode-Typen werden durch gültige Attribute unterschieden. Beispielsweise weist „isComment = true“ auf einen Kommentarknoten hin, „isCloned = true“ auf einen geklonten Knoten usw.

Zu den vNode-Typen gehören: Kommentarknoten, Textknoten, Klonknoten, Elementknoten und Komponentenknoten.

Hier sind die Codes für Kommentarknoten, Textknoten und Klonknoten:

/*
Gültige Attribute des Kommentarknotens: {isComment: true, text: ‚Kommentarknoten‘}
*/
export const createEmptyVNode = (text: Zeichenfolge = '') => {
  const node = neuer VNode()
  node.text = Text
  // Kommentar node.isComment = true
  Rückgabeknoten
}
/*
Gültige Attribute von Textknoten: {text: 'text node'}
*/
Exportfunktion createTextVNode (Wert: Zeichenfolge | Zahl) {
  gibt neuen VNode zurück (undefiniert, undefiniert, undefiniert, String(val))
}

// optimierter flacher Klon
// wird für statische Knoten und Slot-Knoten verwendet, da sie wiederverwendet werden können
// Für statische Knoten und Slot-Knoten // mehrere Renderings, das Klonen vermeidet Fehler, wenn DOM-Manipulationen darauf angewiesen sind
// auf ihrer Ulmenreferenz.
// Knoten klonen - Exportfunktion cloneVNode (vnode: VNode): VNode {
  const geklont = neuer VNode(
    vnode.tag,
    vnode.data,
    //#7975
    // Untergeordnetes Array klonen, um eine Mutation des Originals beim Klonen zu vermeiden
    // ein Kind.
    vnode.children und vnode.children.slice(),
    vnode.text,
    vnode.elm,
    vnode.kontext,
    vnode.componentOptions,
    vnode.asyncFactory
  )
  geklont.ns = vnode.ns
  geklont.isStatic = vnode.isStatic
  geklonter Schlüssel = vnode.key
  geklont.isComment = vnode.isComment
  geklont.fnContext = vnode.fnContext
  geklont.fnOptionen = vnode.fnOptionen
  geklont.fnScopeId = vnode.fnScopeId
  geklont.asyncMeta = vnode.asyncMeta
  // Markiere den Knoten als geklont.isCloned = true
  Rückkehr geklont
}

Durch das Klonen eines Knotens werden dem neuen Knoten tatsächlich alle Eigenschaften des vorhandenen Knotens zugewiesen, und schließlich wird er selbst mit cloned.isCloned = true als geklonter Knoten gekennzeichnet.

Elementknoten haben normalerweise die folgenden vier Attribute:

  • Tag: Knotenname. Zum Beispiel div, p
  • Daten: Daten auf dem Knoten. Zum Beispiel Klasse, Stil
  • children: untergeordnete Knoten
  • Kontext: innerhalb einer Komponente gerendert

Komponentenknoten ähneln Elementknoten und verfügen über zwei eindeutige Eigenschaften:

  • componentOptions: Optionsparameter von Komponentenknoten, wie z. B. propsData, Listener, untergeordnete Elemente, Tags
  • componentInstance: eine Instanz einer Komponente

Patch

Wir haben bereits die erste Aufgabe des virtuellen DOM in Vue vorgestellt: das Bereitstellen eines virtuellen Knotens (vNode), der dem realen Knoten (Node) entspricht. Als Nächstes werden wir die zweite Aufgabe vorstellen: das Vergleichen des neuen virtuellen Knotens mit dem alten virtuellen Knoten, das Ermitteln der Unterschiede und anschließende Aktualisieren der Ansicht.

Die zweite in Vue implementierte Sache heißt Patch, was Patchen oder Reparieren bedeutet. Durch Vergleichen der alten und neuen vNodes, Ermitteln der Unterschiede und anschließendes Patchen basierend auf dem vorhandenen DOM wird die Ansicht aktualisiert.

Das Vergleichen von vNodes zum Auffinden von Unterschieden ist ein Mittel, und das Aktualisieren der Ansicht ist das Ziel.

Das Aktualisieren einer Ansicht ist nichts anderes als das Hinzufügen, Löschen und Aktualisieren von Knoten. Als Nächstes analysieren wir nacheinander, wann und wo ein Knoten hinzugefügt werden soll; wann ein Knoten gelöscht werden soll und welcher gelöscht werden soll; wann ein Knoten aktualisiert werden soll und welcher aktualisiert werden soll;

Hinweis: Wenn vNode und oldVNode unterschiedlich sind, hat vNode Vorrang.

Einen neuen Knoten hinzufügen

Eine Situation ist: Wenn vNode vorhanden ist, aber oldVNode nicht existiert, muss ein neuer Knoten hinzugefügt werden. Am typischsten ist das anfängliche Rendering, da der odlVNode nicht existiert.

Ein anderer Fall ist, dass vNode und oldVNode überhaupt nicht derselbe Knoten sind. Zu diesem Zeitpunkt müssen Sie vNode verwenden, um einen echten Dom-Knoten zu generieren und ihn neben dem echten Dom-Knoten einzufügen, auf den oldVNode zeigt. oldVNode ist ein verlassener Knoten. Beispielsweise in der folgenden Situation:

<div>
  <p v-if="Typ === 'A'">
    Ich bin Knoten A
  </p>
  <span v-else-if="Typ === 'B'">
    Ich bin ein völlig anderer Knoten B als A
  </span>
</div>

Wenn sich der Typ von A nach B ändert, ändert sich der Knoten von p nach span. Da vNode und oldVNode überhaupt nicht derselbe Knoten sind, muss ein neuer Knoten hinzugefügt werden.

Löschen eines Knotens

Wenn der Knoten nur im alten VNode vorhanden ist, löschen Sie ihn einfach.

Knoten aktualisieren

Im vorherigen Abschnitt haben wir die Szenarien zum Hinzufügen neuer Knoten und Löschen von Knoten vorgestellt. Wir haben festgestellt, dass sie eines gemeinsam haben: vNode ist völlig anders als oldVNode.

Ein häufigeres Szenario ist jedoch, dass vNode und oldVNode derselbe Knoten sind. Dann müssen wir einen detaillierteren Vergleich zwischen ihnen (vNode und oldVNode) durchführen und dann den realen Knoten aktualisieren, der oldVNode entspricht.

Für Textknoten ist die Logik natürlich einfach. Vergleichen Sie zunächst die alten und neuen vNodes und stellen Sie fest, dass es sich um denselben Knoten handelt. Ändern Sie dann den Text des Dom-Knotens, der dem alten VNode entspricht, in den Text im vNode. Bei komplexen vNodes, wie etwa einer Baumkomponente in der Schnittstelle, wird dieser Vorgang jedoch kompliziert.

Neuer Knoten - Quellcodeanalyse

Denken Sie darüber nach: Wie bereits erwähnt, gibt es die Typen von vNode: Kommentarknoten, Textknoten, Klonknoten, Elementknoten und Komponentenknoten. Werden alle dieser Typen erstellt und in das DOM eingefügt?

Antwort: Nur Kommentarknoten, Textknoten und Elementknoten. Weil HTML nur diese Typen erkennt.

Da es oben nur die drei Knotentypen gibt, erstellen Sie die entsprechenden Knoten entsprechend den Typen und fügen Sie sie dann an den entsprechenden Positionen ein.

Nehmen wir Elementknoten als Beispiel: Wenn vNode ein Tag-Attribut hat, bedeutet dies, dass es sich um einen Elementknoten handelt. Die Methode createElement wird aufgerufen, um den entsprechenden Knoten zu erstellen, und dann wird die Methode appendChild verwendet, um ihn in den angegebenen übergeordneten Knoten einzufügen. Wenn das übergeordnete Element bereits angezeigt wird, wird es beim Einfügen des darunter liegenden Elements automatisch gerendert. Wenn die Eigenschaft isComment von vNode „true“ ist, weist dies auf einen Kommentarknoten hin. Wenn keines von beiden „true“ ist, weist dies auf einen Textknoten hin.

Normalerweise gibt es im Element untergeordnete Knoten, sodass hier ein rekursiver Prozess beteiligt ist, d. h., die untergeordneten Knoten im vNode werden nacheinander durchlaufen, Knoten erstellt und diese dann rekursiv Schicht für Schicht in den übergeordneten Knoten eingefügt (der übergeordnete Knoten ist der soeben erstellte DOM-Knoten).

Bitte sehen Sie sich den Quellcode an:

// Elementfunktion erstellen createElm (
  vKnoten,
  eingefügteVnodeQueue,
  übergeordnete Ulme,
  sieheElm,
  verschachtelt,
  BesitzerArray,
  Index
) {
  wenn (isDef(vnode.elm) und isDef(ownerArray)) {
    // Dieser Vnode wurde in einem vorherigen Render verwendet!
    // jetzt wird es als neuer Knoten verwendet, das Überschreiben seiner Ulme würde dazu führen
    // mögliche Patch-Fehler später, wenn es als Einfügung verwendet wird
    // Referenzknoten. Stattdessen klonen wir den Knoten bei Bedarf, bevor wir ihn erstellen
    // zugehöriges DOM-Element dafür.
    vnode = BesitzerArray[index] = Klon-VNode(vnode);
  }

  vnode.isRootInsert = !nested; // für Übergang Check eingeben
  wenn (createComponent(vnode, insertedVnodeQueue, parentElm, refElm)) {
    zurückkehren
  }

  var Daten = vnode.data;
  var Kinder = vnode.Kinder;
  var tag = vnode.tag;
  // Hat ein Tag-Attribut, das angibt, dass es sich um einen Elementknoten handelt, if (isDef(tag)) {
    vnode.elm = vnode.ns
      ? nodeOps.createElementNS(vnode.ns, tag)
      //Erstellen Sie das Element. nodeOps ist plattformübergreifend: nodeOps.createElement(tag, vnode);
    setScope(vnode);

    /* istanbul ignorieren wenn */
    {
      // Unterknoten rekursiv erstellen und in den übergeordneten Knoten einfügen createChildren(vnode, children, insertedVnodeQueue);
      wenn (isDef(Daten)) {
        invokeCreateHooks(vnode, insertedVnodeQueue);
      }
      //Füge das dem vnode entsprechende Element in das übergeordnete Element ein insert(parentElm, vnode.elm, refElm);
    }

  // isComment-Eigenschaft gibt einen Kommentarknoten an} else if (isTrue(vnode.isComment)) {
    vnode.elm = nodeOps.createComment(vnode.text);
    //Übergeordneten Knoten einfügeninsert(parentElm, vnode.elm, refElm);
  // Sonst ist es ein untergeordneter Knoten} else {
    vnode.elm = nodeOps.createTextNode(vnode.text);
    //Übergeordneten Knoten einfügeninsert(parentElm, vnode.elm, refElm);
  }
}

// Untergeordnete Knoten rekursiv erstellen und in den übergeordneten Knoten einfügen. vnode stellt den übergeordneten Knoten dar. Funktion createChildren (vnode, children, insertedVnodeQueue) {
  wenn (Array.isArray(Kinder)) {
    wenn (Prozess.Umgebung.NODE_ENV !== 'Produktion') {
      checkDuplicateKeys(untergeordnete Elemente);
    }
    //Erstelle nacheinander untergeordnete Knoten und füge sie in den übergeordneten Knoten ein for (var i = 0; i < children.length; ++i) {
      createElm(Kinder[i], eingefügteVnodeQueue, vnode.elm, null, true, Kinder, i);
    }
  } sonst wenn (isPrimitive(vnode.text)) {
    nodeOps.appendChild(vnode.elm, nodeOps.createTextNode(String(vnode.text)));
  }
}

Löschen eines Knotens - Quellcodeanalyse

Das Löschen eines Knotens ist sehr einfach. Schauen Sie sich den Quellcode direkt an:

// Einen Satz angegebener Knoten löschen function removeVnodes (parentElm, vnodes, startIdx, endIdx) {
  für (; startIdx <= endIdx; ++startIdx) {
    var ch = vnodes[startIdx];
    wenn (isDef(ch)) {
      if (isDef(ch.tag)) {
        entfernenAndInvokeRemoveHook(ch);
        invokeDestroyHook(ch);
      } sonst { // Textknoten
        // Einen Knoten löschenremoveNode(ch.elm);
      }
    }
  }
}

// Einen einzelnen Knoten löschen Funktion removeNode (el) {
  var parent = nodeOps.parentNode(el);
  // Element wurde möglicherweise aufgrund von v-html / v-text bereits entfernt
  wenn (isDef(übergeordnet)) {
    // nodeOps kapselt die plattformübergreifende Methode nodeOps.removeChild(parent, el);
  }
}

Oben finden Sie den detaillierten Inhalt der Schnellstartanleitung für Vue Virtual DOM. Weitere Informationen zu Vue Virtual DOM finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

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
  • Detaillierte Erläuterung des virtuellen DOM in der Vue-Quellcodeanalyse
  • 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

<<:  Eine kurze Analyse des Unterschieds zwischen FIND_IN_SET() und IN in MySQL

>>:  Installieren Sie Memcached und die PHP Memcached-Erweiterung unter CentOS

Artikel empfehlen

Installieren Sie MySQL 5.7.17 im Win10-System

Das Betriebssystem Win10 MySQL ist die 64-Bit-ZIP...

Vue+echarts realisiert gestapelte Balkendiagramme

In diesem Artikel wird der spezifische Code von V...

So implementieren Sie das Abfangen von URIs im Nginx-Standort

veranschaulichen: Stamm und Alias ​​im Standort D...

WeChat-Applet implementiert Sortierfunktion basierend auf Datum und Uhrzeit

Ich habe vor kurzem ein kleines Programmierprojek...

Webdesign-Referenz Firefox-Standardstil

Obwohl das W3C einige Standards für HTML festgeleg...

CSS3 verwendet var()- und calc()-Funktionen, um Animationseffekte zu erzielen

Wissenspunkte in der Vorschau anzeigen. Animation...

So überwachen Sie MySQL mit Zabbix

Dokumentation zur Zabbix-Bereitstellung Nach der ...

Schritte zur Installation von MySQL 5.7.10 auf Windows Server 2008 R2

Installation mithilfe des MSI-Installationspakets...

Der Unterschied zwischen HTML-Block-Level-Tags und Inline-Tags

1. Blockebenenelement: bezieht sich auf die Fähigk...

mysql ist keine interne Befehlsfehlerlösung

Der Fehler „mysql ist kein interner Befehl“ tritt...

Detaillierte Erklärung des JavaScript-Stacks und der Kopie

Inhaltsverzeichnis 1. Definition des Stapels 2. J...