Einfache Implementierung von Mini-Vue-Rendering

Einfache Implementierung von Mini-Vue-Rendering

Vorwort

Die aktuellen Mainstream-Frameworks Vue und React werden beide über Virtual Dom implementiert, was die Effizienz der Seitendarstellung durch Virtual Dom-Technologie verbessert. In Vue schreiben wir HTML-Code in die Vorlage und in React schreiben wir HTML-Code in eine interne Renderfunktion. Nachdem diese Funktion durch jsx kompiliert wurde, gibt sie tatsächlich eine h-Funktion aus, die unser virtuelles Dom ist. Das Folgende ist eine einfache Implementierung eines virtuellen Doms, das ein reales Dom rendert, sowie die Update-Methode.

Ziel

Es realisiert hauptsächlich die folgenden drei Funktionen:

  • Gibt Vnodes über die h-Funktion zurück;
  • Verwenden Sie die Mount-Funktion, um den virtuellen Dom auf dem realen Knoten zu mounten.
  • Die Patch-Funktion wird zum Aktualisieren des DOM durch Vergleichen von newVnodes mit oldVnodes verwendet.

Erster Schritt:

Erstellen Sie einen Knoten mit der ID-App im Body-Tag. Der virtuelle Knoten wird später auf diesem Knoten bereitgestellt und renderer.js wird verwendet, um die oben genannten drei Funktionen zu implementieren.

<Text>
  <div id="app"></div>
  <script src="./renderer.js"></script>
</body>

Schritt 2:

Schreiben Sie die h-Funktion, um Tag (Tag-Element), Props (Eigenschaftsobjekt) und Kinder (untergeordnete Knoten) zurückzugeben. Einfach ausgedrückt ist der virtuelle Dom ein gewöhnliches JavaScript-Objekt.

// renderer.js
 
const h = (Tag, Requisiten, untergeordnete Elemente) => {
  zurückkehren {
    Etikett,
    Requisiten,
    Kinder
  }
}

Werfen wir also einen kurzen Blick auf die Ausgabe des folgenden Codes durch diese h-Funktion.

const vdom = h("div", {Klasse: "Header"}, [
  h("h2", null, "Hallo Welt"),
  h("h2", {id: 0}, h("span", null, "Spanne")) // Wenn die Eigenschaften keinen Wert haben, muss ein Nullwert übergeben werden, er kann nicht weggelassen werden]);
Konsole.log(vdom);

Wie aus der folgenden Abbildung ersichtlich ist, wird uns durch die h-Funktion ein JavaScript-Objekt zurückgegeben, bei dem es sich um den virtuellen Dom handelt, der einen Baumknoten bildet.

Wie mounten wir also diese Vnodes zum realen Knoten? Schauen wir uns nun Schritt drei an.

Schritt 3:

Wir erstellen zunächst eine Mount-Funktion, die zwei Parameter übergeben muss. Der erste sind die Vnodes, die wir gerade über die h-Funktion zurückgegeben haben, und der zweite Parameter ist, auf welchem ​​Knoten wir diese Vnodes mounten müssen. Sehen wir uns den Code an:

const mount = (vnodes, app) => {
  // Erstellen Sie einen Knoten über den Tag-Wert in vnodes, z. B. („div“, „h2“) // Speichern Sie auch ein echtes DOM im vnodes-Objekt, um zukünftige Aktualisierungen, Ergänzungen usw. zu erleichtern. const el = vnodes.el = document.createElement(vnodes.tag); 
  // Nachdem wir diesen Knoten erhalten haben, fügen wir Eigenschaften hinzu, indem wir den Props-Wert beurteilen, wenn (vnodes.props) {
    für (let-Schlüssel in vnodes.props) {
      // Hier treffen wir nach Erhalt des Schlüsselwerts in den Props eine Beurteilung: let value = vnodes.props[key];
      wenn (Schlüssel.startetMit('ein')) {
        // Wenn der Benutzer beispielsweise onClick="changeData" schreibt, wird dies als Ereignislistenerfunktion verarbeitet el.addEventListener(key.slice(2).toLowerCase(), value)
      } anders {
        el.setAttribute(Schlüssel, Wert)
      }
      // Nachfolgend finden Sie einige Urteile, z. B. Anweisungen, v-if usw. für die Grenzverarbeitung}
  }
  // Nach der Verarbeitung der Eigenschaften ist der letzte Knoten Children if (vnodes.children) {
    wenn (Typ von vnodes.children === 'Zeichenfolge') {
      // Wenn dies ein String-Typ ist, können Sie ihn direkt zum Knoten el.textContent = vnodes.children hinzufügen.
    } anders {
      // In diesem Fall handelt es sich um einen Array-Typ, der untergeordnete Knoten enthält und dann durch Durchlauf untergeordnete Knoten generiert vnodes.children.forEach(vnode => {
        // Den untergeordneten Knoten rekursiv erneut in den aktuellen Knoten einhängen mount(vnode, el)
      })
    }
  }
  //Mounten Sie abschließend diesen realen Knoten in dem App-Knoten, den wir in app.appendChild(el) übergeben haben.
}
const app = document.querySelector("#app")
mount(vdom, app)

Schauen wir uns die tatsächliche Auswirkung der Montage über die Mount-Funktion an:

Bisher haben wir einen realen DOM durch einen virtuellen DOM erstellt. Wie aktualisieren wir diese DOMs in Vue? Als nächstes erstellen wir eine Patch-Funktion (Update):

Schritt 4:

Über die Patch-Funktion müssen wir zwei Parameter (vnodes1, vnodes2) übergeben, nämlich den neuen virtuellen Dom und den alten virtuellen Dom. Durch den Vergleich des neuen und des alten virtuellen Doms können wir angeben, welche Knoten aktualisiert werden sollen. (Der Schlüsselwert wird hier nicht berücksichtigt. Wenn Sie den Schlüsselwert benötigen, können Sie den Link überprüfen: https://www.jb51.net/article/219078.htm)

//Patch-Funktion n1: alter Knoten, n2: neuer Knoten // Im Vue-Quellcode werden der alte und der neue Vnode jeweils durch n1 und n2 dargestellt const patch = (n1, n2) => {
  // Oben haben wir das Knotenattribut el über die Mount-Funktion zu n2 hinzugefügt und es an n2 gebunden const el = n2.el = n1.el
  // Beginnen Sie zunächst mit den Tags in den beiden if (n1.tag == n2.tag) {
    // n1 und n2 haben das gleiche Tag, dann vergleiche die Eigenschaften
    const n1Props = n1.props || {};
    const n2Props = n2.props || {};
    // Hole Props jeweils von n1 und n2 und vergleiche für (let key in n2Props) {
      // Alle Schlüssel in n2 herausnehmen und prüfen, ob der Schlüsselwert von n2 mit dem Schlüsselwert von n1 übereinstimmt const n1Value = n1Props[key] || '';
      const n2Value = n2Props[Schlüssel] || '';
      wenn (n1Wert !== n2Wert) {
        wenn (Schlüssel.startetMit('ein')) {
          // Wenn der Benutzer beispielsweise onClick="changeData" schreibt, wird dies als Event-Listener-Funktion verarbeitet el.addEventListener(key.slice(2).toLowerCase(), n2Value)
        } anders {
          el.setAttribute(Schlüssel, n2Wert)
        }
      }
      //Wenn sie gleich sind, wird keine Verarbeitung durchgeführt}
    für (let-Schlüssel in n1Props) {
      const alterWert = n1Props[Schlüssel];
      if (!(Schlüssel in n2Props)) {
        wenn (Schlüssel.startetMit('ein')) {
          el.removeEventListener(Schlüssel.Slice(2).toLowerCase(), alterWert)
        } anders {
          el.removeAttribute(Schlüssel)
        }
      }
    }
  } anders {
    // Tag ist anders, hole den übergeordneten Knoten von n1 const n1Parent = n1.el.parentElement;
    // Entferne den alten Knoten vom übergeordneten Knoten durch removeChild und mounte dann n2 zum übergeordneten Knoten n1Parent.removeChild(n1.el); //n1.el ist der echte Dom-Knoten, der dem Objekt durch die Mount-Funktion mount(n2, n1Parent) hinzugefügt wurde.
  }
  // Zum Schluss verarbeiten wir die untergeordneten Elemente, was relativ kompliziert ist. // Untergeordnete Elemente können Zeichenfolgen oder Arrays sein, also schauen wir uns zuerst an, wie die Zeichenfolge verarbeitet wird. const n1Children = n1.children || [];
  const n2Children = n2.children || [];
  wenn (Typ von n2Children === "Zeichenfolge") {
    // Wenn der neue Knoteninhalt eine Zeichenfolge ist, verwenden Sie direkt innerhtml, um el.innerHtml = n2Children zu ersetzen.
  } anders {
    // Die folgende Situation ist, wenn n2.children ein Array ist, if (typeof n1.children === "string") {
      // n1.children ist ein String, n2.children ist ein Array el.innerHtml = ''; // Erst den Knoteninhalt prüfen, dann neuen Inhalt hinzufügen mount(n2.children, el)
    } anders {
      // Wenn beides Array-Typen sind, wird der Schlüsselwert hier nicht berücksichtigt const minLength = Math.min(n1Children.length, n2Children.length);
      für (sei i = 0; i < minLength; i++) {
        Patch(n1Kinder[i], n2Kinder[i]);
      }
      wenn (n2Kinder.Länge > n1Kinder.Länge) {
        n2Children.slice(minLength).fürJedes(Element => {
          einhängen(Artikel, el)
        })
      }
      wenn (n2Kinder.Länge < n1Kinder.Länge) {
        n1Children.slice(minLength).fürJedes(Element => {
          el.entfernenKind(item.el)
        })
      }
    }
  }
}

Das Obige ist eine einfache Implementierung der Patch-Funktion, die eigentlich das ist, was wir den Diff-Algorithmus nennen (natürlich wird der Schlüsselwert hier nicht berücksichtigt und es können nur zwei nacheinander verglichen werden), und der Vergleich wird auf derselben Ebene durchgeführt. Lassen Sie uns nun simulieren und demonstrieren, ob das Update erfolgreich sein kann:

const vdom = h("div", {Klasse: "Header"}, [
  h("h2", null, "Hallo Welt"),
  h("h2", {id: 0}, [h("span", null, "Spanne")]) // Wenn die Eigenschaften keinen Wert haben, muss ein Nullwert übergeben werden, er kann nicht weggelassen werden]);
const app = document.querySelector("#app")
mount(vdom, app)
setTimeout(()=> { // Übergebe die neuen und alten Vnodes nach 3 Sekunden an den Patch
  const vdom1 = h("div", {Klasse: "Header"}, [
    h("h3", null, "Hallo Welt"),
    h("span", null, "Spanne")
  ])
  Patch(vdom, vdom1)
},3000)

Aus der folgenden Abbildung können wir erkennen, dass der virtuelle DOM-Updateknoten einfach implementiert wurde.

Zusammenfassen

Es implementiert einfach den virtuellen Dom, um echte Knoten zu generieren, und aktualisiert diese dann durch Patches. Wenn Sie sich den Quellcode noch einmal ansehen, können Sie besser verstehen, wie der Renderer von Vue implementiert ist.

Dies ist das Ende dieses Artikels über die einfache Implementierung von Mini-Vue-Rendering. Weitere relevante Inhalte zum Mini-Vue-Rendering finden Sie in früheren Artikeln auf 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:
  • Vue + ElementUI realisiert die Methode des dynamischen Renderings und der visuellen Konfiguration von Formularen
  • Eine kurze Diskussion zum V-For-Loop-Rendering in vue.js
  • Vue ruft die Methode auf, nachdem das Rendern der Seitendaten abgeschlossen ist
  • Vue implementiert eine Steuerung der Bildlaufleistenposition nach dem Rendern der Daten (empfohlen)
  • Lösen Sie das Problem, dass Vue das Array durch die folgende Tabelle ändert und die Seite nicht gerendert wird

<<:  Detaillierter Code zum Erstellen eines Mehrpersonen-Video-Chat-Dienstes basierend auf WebRTC unter Ubuntu

>>:  Methode und Einführung der Tabellenindexdefinition in MySQL

Artikel empfehlen

Detaillierte Erklärung zur Verwendung des Alias-Befehls unter Linux

1. Verwendung von Pseudonymen Mit dem Alias-Befeh...

Details zur Verwendung regulärer Ausdrücke in MySQL

Inhaltsverzeichnis 1. Einleitung 2. Bereiten Sie ...

Detaillierte Erklärung zur Installation von MariaDB 10.2.4 auf CentOS7

CentOS 6 und frühere Versionen stellen MySQL-Serv...

Warum kann das in HTML eingebettete Video im MP4-Format nicht abgespielt werden?

Der folgende Code befindet sich in meiner test.htm...

Grafisches Tutorial zur Installation und Konfiguration von MySQL 5.7.17 winx64

Ich habe die vorherigen Hinweise zur Installation...

Detaillierte Erläuterung zur Verwendung der WeChat-Miniprogrammkarte

In diesem Artikelbeispiel wird der spezifische Im...

So laden Sie Komponentenbibliotheken von Drittanbietern bei Bedarf in Vue3

Vorwort Nehmen Sie Element Plus als Beispiel, um ...

So starten Sie Tomcat mit jsvc (als normaler Benutzer ausführen)

Einführung in jsvc In der Produktion sollte Tomca...

JS-Dekorationsmuster und TypeScript-Dekoratoren

Inhaltsverzeichnis Einführung in das Decorator-Mu...

Tägliche Studiennotizen im HTML-Designmuster

Studiennotizen zu HTML-Entwurfsmustern Diese Woch...

Fallbeispiel zur TypeScript-Schnittstellendefinition

Die Rolle der Schnittstelle: Schnittstelle, auf E...