Detaillierte Erklärung des virtuellen DOM und des Diff-Algorithmus in React

Detaillierte Erklärung des virtuellen DOM und des Diff-Algorithmus in React

Die Rolle des virtuellen DOM

Zunächst müssen wir wissen, welches Problem durch die Einführung des virtuellen DOM gelöst werden soll. Es löst das Problem der geringen Effizienz bei unseren häufigen direkten DOM-Operationen. Warum ist es so ineffizient, das DOM direkt zu manipulieren?

Wenn wir beispielsweise ein Div erstellen, können wir in der Konsole überprüfen, ob dieses Div viele Eigenschaften hat oder erbt. Insbesondere wenn wir JS zum Bedienen von DOM verwenden, ist unser DOM selbst sehr kompliziert und JS-Operationen werden viel Zeit in Anspruch nehmen, aber wir können die DOM-Elemente selbst nicht steuern. Daher löst virtuelles DOM das Problem des JS-Bedienens von DOM , wodurch die Anzahl der DOM-Operationen tatsächlich reduziert wird.

Einfache Implementierung eines virtuellen DOM

Virtual DOM ist, wie der Name schon sagt, ein Fake-DOM. Unser reales DOM ist auf der Seite gemountet, während sich unser virtuelles DOM im Speicher befindet. Dies erfordert, dass wir den echten DOM in ein Objekt abstrahieren und im Speicher ablegen. Dieses Objekt kann vom folgenden Typ sein:

var Element = {
      tagName: 'div',
      Requisiten: {
        Klasse: "Box"
      },
      Kinder: {
        {
          tagName: "p",
          Requisiten: {
            Klasse: "p1"
          },
          Kinder: ['Ich bin p1']
        }, 
         {
          tagName: "p",
          Requisiten: {
            Klasse: "p2"
          },
          Kinder: ['Ich bin p2']
        }, 
        {
          tagName: "p",
          Requisiten: {
            Klasse: "p3"
          },
          Kinder: ['Ich bin p3']
        },
      }
    }

Wenn wir ein solches Objekt konstruieren möchten, können wir einen Konstruktor wie folgt kapseln:

Funktion Element(tagName, Requisiten, untergeordnete Elemente) {
    this.tagName = Tagname
    this.props = Requisiten
    this.children = Kinder
}

Mit diesem Objekt müssen wir diesen virtuellen DOM in den realen DOM umwandeln. Wir können die folgende Methode schreiben:

Element.prototype.render = Funktion () {
    const { tagName, Requisiten, untergeordnete Elemente } = dies
    var el = document.createElement(tagName)
    für (Schlüssel in Requisiten) {
        el.setAttribute(Schlüssel, Requisiten[Schlüssel])
    }
    Kinder.fürJedes((Element) => {
        const childEl = (Item-Instanz des Elements)?
              item.render() :
        document.createTextNode(Element)
        el.appendChild(KindEl)
    })
    Rückkehr el
}

Schließlich können wir dieses Objekt erstellen, die Methode render() aufrufen und dann appendChild an den Textkörper anhängen:

let virtualDom = neues Element('div', { Klasse: 'box' }, [
    neues Element('p', { Klasse: 'p1' }, ['Ich bin p1']),
    neues Element('p', { Klasse: 'p2' }, ['Ich bin p2']),
    neues Element('p', { Klasse: 'p3' }, ['Ich bin p3']),
])

lass a = virtualDom.render()
Dokument.Body.AnhängenKind(a)

Diff-Algorithmus

Lassen Sie uns zunächst die Rolle des Diff-Algorithmus verstehen

Wenn sich unser virtueller DOM ändert, wird in unserem Speicher ein neuer virtueller DOM generiert. Wenn wir diese neue virtuelle DOM-Struktur direkt verwenden, führt dies zu vielen wiederholten Renderings. Daher wird zu diesem Zeitpunkt die Rolle des Diff-Algorithmus reflektiert. Diff vergleicht die neuen und alten virtuellen DOM-Bäume, findet die Unterschiede, zeichnet sie auf und wendet die aufgezeichneten Unterschiede dann auf den realen DOM-Baum an.

Prinzip:

Der Diff-Algorithmus führt eine Tiefensuche durch die neuen und alten Bäume durch und fügt jedem Knoten eine eindeutige Kennung hinzu.

Dieser Prozess ist in 2 Schritte unterteilt

  • Finden Sie die Unterschiede zwischen den beiden Bäumen und zeichnen Sie sie in einem Pseudo-Array auf.
  • Wenden Sie diese Unterschiede auf den tatsächlichen DOM-Baum an

Die Operationen auf DOM können grundsätzlich in 4 Typen unterteilt werden

  • Löschen, Verschieben und Hinzufügen von untergeordneten Knoten zu Knoten
  • Knotenbeschriftungen ändern
  • Für Textknoten ändern Sie den Knotentext
  • Knoteneigenschaften ändern

Im Folgenden wird dieser Vorgang grob in Form von Pseudocode durchgegangen

// Diff-Funktion, vergleiche zwei Bäume Funktion diff(oldTree, newTree) {
    var patches = {}; // Pseudo-Array, Unterschiede aufzeichnen // Fehlerbeurteilungen für 4 Knotentypen vornehmen dfWork(oldTree, newTree, patches, index)

    Rückkehr-Patches

}
Funktion dfWork(alterBaum, neuerBaum, Patches, Index) {
    lass currentPatch = []

    if (1) { // Lösche den Knoten currentPatch.push()
    } else if (3) { // Ändere den Text des Knotens currentPatch.push()

    } sonst { // Eigenschaften des Knotens ändern. Untergeordnete Elemente prüfen. // Einen Diff-Algorithmus für die Eigenschaften ausführen und die Änderungen in Patches aufzeichnen.
        currentPatch.push({ Typ: Patch.PROPS, Eigenschaften: propsPatches })
        // Dann müssen Sie einen Diff-Algorithmus auf den untergeordneten Knoten ausführen diffChildren(oldNode.children, newNode.children, index, patches, currentPatch)
    }
}
Funktion diffChildren(alteChildren, neueChildren, Index, Patches, aktuellerPatch) {

    // Diff-Algorithmus auf untergeordneten Knoten ausführen, untergeordnete Knoten durchlaufen, dfWork rekursiv aufrufen und Unterschiede vornehmen, um Patches zu erhalten

}
// Die Änderungen auf die aktuelle DOM-Baumfunktion anwenden patch(node, patches) {
    // Knoten ist der alte DOM-Baum, Patch-Änderungen.
    // Wir werden die Patches durchlaufen und die Knoten den Patches zuordnen.
}
Funktion applyPatch(Knoten, Patches) {
    // Da jeder Knoten mehrere Änderungen aufweisen kann, müssen wir auch switch (patches.type) { durchlaufen.
        Fall REPLACE: // Knoten ersetzen // node.render() 
            brechen;
        Case REORDER: // Verschieben, löschen und neue untergeordnete Knoten hinzufügen.

            brechen;
        Fall-Props:
            // setzeProps
            brechen;
        case TEXT: // Ändere den Knotentext // node.nodeValue
            brechen;

        Standard:
            brechen;
    }
}

Referenzdokument: Detaillierte Analyse: So implementieren Sie einen virtuellen DOM-Algorithmus. Autor: livoras, integrierter Quellcode.

Dies ist das Ende dieses Artikels über virtuelle DOM- und Diff-Algorithmen in React. Weitere relevante Inhalte zu virtuellen DOM- und Diff-Algorithmen in React finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Kennen Sie den Diff-Algorithmus in React?
  • Detaillierte Analyse des Diff-Algorithmus in React
  • React Diff-Algorithmus-Quellcodeanalyse
  • Eine kurze Diskussion zur Analyse des Diff-Algorithmus aus dem React-Rendering-Prozess
  • Beispielimplementierung des React-Diff-Algorithmus
  • Ideen zur Implementierung des React-Diff-Algorithmus und Prinzipanalyse

<<:  Lösung für den Konflikt zwischen Nginx und Backend-Port

>>:  Detaillierte Analyse des binlog_format-Modus und der Konfiguration in MySQL

Artikel empfehlen

Grafisches Tutorial zur Installation und Konfiguration von MySQL (CentOS7)

1. Systemumgebung [root@localhost-Startseite]# ca...

Detaillierte Erklärung zu Padding und Abkürzungen im CSS-Boxmodell

Wie oben gezeigt, sind Füllwerte zusammengesetzte...

Lösung für den ONLY_FULL_GROUP_BY-Fehler in Mysql5.7 und höher

Während des jüngsten Entwicklungsprozesses handel...

So verwenden Sie vite zum Erstellen einer Vue3-Anwendung

1. Installation Tipp: Derzeit gibt es kein offizi...

So konfigurieren Sie mehrere Projekte mit demselben Domänennamen in Nginx

Es gibt zwei Möglichkeiten, mit Nginx mehrere Pro...

Detaillierte Erklärung der TMPF-Mounts im Docker-Datenspeicher

Bevor Sie diesen Artikel lesen, hoffe ich, dass S...

So entwickeln Sie Uniapp mit vscode

Da ich immer vscode zur Entwicklung von Front-End...

So zeigen Sie den Typ des gemounteten Dateisystems in Linux an

Vorwort Wie Sie wissen, unterstützt Linux viele D...

Lösung für SQL Server-Datenbankfehler 5123

Weil ich ein Datenbank-Tutorial habe, das auf SQL...