Implementierungsmethode für die bidirektionale Bindung von Vue-Daten

Implementierungsmethode für die bidirektionale Bindung von Vue-Daten

1. Einleitung

Dieser Artikel ist für Anfänger geeignet, die den Vue-Quellcode lernen. Nach der Lektüre haben Sie ein allgemeines Verständnis des Prinzips der bidirektionalen Datenbindung in Vue und verstehen die drei Hauptrollen von Observer, Compile und Wathcer (wie in der folgenden Abbildung dargestellt) und ihre Funktionen.

In diesem Artikel werden Sie Schritt für Schritt durch die Implementierung einer einfachen Version der bidirektionalen Datenbindung geführt. In jedem Schritt wird das in diesem Schritt zu lösende Problem und der Grund für die Art und Weise, wie der Code geschrieben wird, detailliert analysiert. Daher hoffe ich, dass Sie nach dem Lesen dieses Artikels selbst eine einfache Version der bidirektionalen Datenbindung implementieren können.

2. Code-Implementierung

2.1 Zweckanalyse

Der mit diesem Artikel zu erzielende Effekt ist in der folgenden Abbildung dargestellt:

Die in diesem Artikel verwendeten HTML- und JS-Hauptcodes sind wie folgt:

<div id="app">
  <h1 v-text="msg"></h1>
  <Eingabetyp="Text" v-Modell="Nachricht">
  <div>
    <h1 v-text="msg2"></h1>
    <Eingabetyp="text" v-modell="msg2">
  </div>
</div>
lass vm = neues Vue({
    el: "#app",
    Daten: {
      Nachricht: "Hallo Welt",
      msg2: „hallo xiaofei“
    }
  })

Dazu gehen wir in drei Schritten vor:

  • Schritt 1: Synchronisieren Sie die Daten in den Daten mit der Seite, um die Initialisierung von M ==> V zu erreichen;
  • Schritt 2: Wenn ein Wert in das Eingabefeld eingegeben wird, wird der neue Wert mit den Daten synchronisiert, um die Bindung von V ==> M zu erreichen.
  • Schritt 3: Wenn die Daten aktualisiert werden, wird eine Seitenänderung ausgelöst, wodurch die Bindung von M ==> V realisiert wird.

2.2 Implementierungsprozess

2.2.1 Zugangscode

Zuerst müssen wir eine Vue-Klasse erstellen, die ein Optionsobjekt empfängt. Gleichzeitig müssen wir die gültigen Informationen im Optionsobjekt speichern.

Dann haben wir drei Hauptmodule: Observer, Compile und Wathcer. Unter ihnen wird Observer zum Daten-Hijacking verwendet, Compile wird zum Parsen von Elementen verwendet und Wathcer ist ein Beobachter. Sie können den folgenden Code schreiben: (Es ist nicht erforderlich, die drei Konzepte Observer, Compile und Wathcer im Detail zu studieren, da sie später ausführlich erläutert werden.)

Klasse Vue {
    // Empfange das übergebene Objekt Konstruktor(Optionen) {
      // Gültige Informationen speichern this.$el = document.querySelector(options.el);
      dies.$data = Optionen.data;

      //Container: {Attribut 1: [wathcer1, wathcer2...], Attribut 2: [...]}, wird zum Speichern jedes Attributbeobachters verwendet. $watcher = {};

      // Elemente analysieren: Implementieren von Compile
      this.compile(this.$el); // Um ​​das Element zu analysieren, müssen Sie das Element übergeben in // Daten kapern: Observer implementieren
      this.observe(this.$data); // Um ​​Daten zu kapern, müssen Sie die Daten übergeben}
    kompilieren() {}
    beobachten() {}
  }

2.2.2 Seiteninitialisierung

In diesem Schritt müssen wir die Seite initialisieren, das heißt, die V-Text- und V-Model-Anweisungen analysieren und die Daten in Daten auf der Seite rendern.

Der Schlüssel zu diesem Schritt besteht darin, die Kompilierungsmethode zu implementieren. Wie also wird das el-Element analysiert? Die Idee ist folgende:

  • Zuerst müssen wir alle untergeordneten Knoten unter el abrufen und dann diese untergeordneten Knoten durchlaufen. Wenn die untergeordneten Knoten untergeordnete Knoten haben, müssen wir die Idee der Rekursion verwenden.
  • Durchlaufen Sie die untergeordneten Knoten, um alle Elemente mit Anweisungen zu finden, und rendern Sie die entsprechenden Daten auf der Seite.

Der Code lautet wie folgt: (sehen Sie sich hauptsächlich den Kompilierungsteil an)

Klasse Vue {
    // Empfange das übergebene Objekt Konstruktor(Optionen) {
      // Nützliche Informationen erhalten this.$el = document.querySelector(options.el);
      dies.$data = Optionen.data;

      // Container: {attribute1: [wathcer1, wathcer2...], attribute2: [...]}
      dies.$watcher = {};

      // 2. Elemente analysieren: Implementieren von Compile
      this.compile(this.$el); // Um ​​das Element zu parsen, musst du das Element übergeben in // 3. Daten kapern: Observer implementieren
      this.observe(this.$data); // Um ​​Daten zu kapern, müssen Sie die Daten übergeben}
    kompilieren(el) {
      // Analysieren Sie jeden untergeordneten Knoten unter dem Element, um el.children zu erhalten.
      // Hinweis: children gibt einen Elementsatz zurück, childNodes gibt einen Knotensatz zurück let nodes = el.children;

      // Analysiere die Anweisungen für jeden untergeordneten Knoten for (var i = 0, length = nodes.length; i < length; i++) {
        sei Knoten = Knoten[i];
        // Wenn der aktuelle Knoten untergeordnete Elemente hat, den Knoten rekursiv analysieren if(node.children){
          dies.kompilieren(Knoten);
        }
        // Elemente mit der v-text-Direktive analysieren if (node.hasAttribute("v-text")) {
          let attrVal = node.getAttribute("v-text");
          node.textContent = this.$data[attrVal]; // Seite rendern}
        // Elemente mit v-model-Direktiven analysieren if (node.hasAttribute("v-model")) {
          let attrVal = node.getAttribute("v-Modell");
          Knoten.Wert = dies.$data[attrVal];
        }
      }
    }
    beobachten(Daten) {}
  }

Auf diese Weise haben wir die Initialisierung der Seite erreicht.

2.2.3 Ansichten beeinflussen Daten

Da die Eingabe über eine V-Modell-Anweisung verfügt, müssen wir eine solche Funktion implementieren: Wenn Zeichen in das Eingabefeld eingegeben werden, ändern sich die in den Daten gebundenen Daten entsprechend.

Wir können ein Eingabeereignis an das Eingabeelement binden. Die Auswirkung des Ereignisses besteht darin, die entsprechenden Daten in Daten in den Wert in Eingabe zu ändern.

Der Implementierungscode dieses Teils ist relativ einfach. Sie können ihn verstehen, indem Sie sich die markierte Stelle ansehen. Der Code lautet wie folgt:

Klasse Vue {
    Konstruktor(Optionen) {
      dies.$el = document.querySelector(options.el);
      dies.$data = Optionen.data;
      
      dies.$watcher = {};  

      dies.kompilieren(dies.$el);

      dies.beobachten(diese.$daten);
    }
    kompilieren(el) {
      lass Knoten = el.children;

      für (var i = 0, Länge = Knoten.Länge; i < Länge; i++) {
        sei Knoten = Knoten[i];
        wenn(Knoten.Kinder){
          dies.kompilieren(Knoten);
        }
        wenn (node.hasAttribute("v-text")) {
          let attrVal = node.getAttribute("v-text");
          node.textContent = dies.$data[attrVal];
        }
        wenn (node.hasAttribute("v-model")) {
          let attrVal = node.getAttribute("v-Modell");
          Knoten.Wert = dies.$data[attrVal];
          // Schau mal hier! ! Nur noch drei Codezeilen! !
          node.addEventListener("Eingabe", (ev)=>{
            dies.$data[attrVal] = ev.target.value;
            // Sie können versuchen, es hier auszuführen: console.log(this.$data),
            // Sie können sehen, dass sich jedes Mal, wenn Sie Text in das Eingabefeld eingeben, auch der Nachrichtenwert in den Daten ändert})
        }
      }
    }
    beobachten(Daten) {}
  }

2.2.4 Datenauswirkungsansicht

Bisher haben wir erreicht, dass die Daten in den Daten automatisch aktualisiert werden, wenn wir Zeichen in das Eingabefeld eingeben.

Die Hauptaufgabe dieses Abschnitts besteht darin, dass bei einer Aktualisierung der Daten die an die Daten gebundenen Elemente automatisch die Ansicht auf der Seite aktualisieren. Die konkreten Vorstellungen sind wie folgt:

1) Wir implementieren eine Watcher-Klasse, die über eine Update-Methode zum Aktualisieren der Seite verfügt. Der Beobachtercode lautet wie folgt:

Klasse Watcher{
    Konstruktor(Knoten, aktualisiertesAttr, vm, Ausdruck){
      //Speichere die übergebenen Werte. Diese Werte werden beim Rendern der Seite verwendet. this.node = node;
      dies.updatedAttr = updatedAttr;
      dies.vm = vm;
      dieser.Ausdruck = Ausdruck;
      dies.update();
    }
    aktualisieren(){
      dieser.Knoten[dieses.updatedAttr] = diese.vm.$data[dieser.Ausdruck];
    }
  }

2) Überlegen Sie, welchen Daten wir Beobachter hinzufügen sollten? Wann sollten den Daten Beobachter hinzugefügt werden?

Beim Parsen des Elements, wenn die Anweisungen für V-Text und V-Modell analysiert werden, bedeutet dies, dass dieses Element in beide Richtungen an die Daten gebunden werden muss. Daher fügen wir dem Container zu diesem Zeitpunkt einen Beobachter hinzu. Wir müssen eine Datenstruktur wie diese verwenden: {Attribut 1: [wathcer1, wathcer2...], Attribut 2: [...]}. Wenn das nicht ganz klar ist, können Sie die folgende Abbildung sehen:

Sie können sehen, dass in der Vue-Instanz ein $watcher-Objekt vorhanden ist. Jedes Attribut von $watcher entspricht den Daten, die gebunden werden müssen, und der Wert ist ein Array, in dem die Beobachter gespeichert werden, die die Daten beobachtet haben. (Hinweis: Der Vue-Quellcode erstellt speziell eine Klasse namens Dep, die dem hier erwähnten Array entspricht. Dieser Artikel ist eine vereinfachte Version, daher werde ich ihn nicht im Detail vorstellen.)

3) Daten kapern: Verwenden Sie den Getter und Setter der Accessor-Eigenschaft des Objekts, um eine Aktion auszulösen, wenn die Daten aktualisiert werden. Der Hauptzweck dieser Aktion besteht darin, allen Beobachtern, die die Daten beobachtet haben, die Ausführung der Aktualisierungsmethode zu ermöglichen.

Um zusammenzufassen, was wir in diesem Abschnitt tun müssen:

  1. Implementieren Sie eine Watcher-Klasse;
  2. Fügen Sie beim Parsen von Anweisungen (d. h. in der Kompilierungsmethode) Beobachter hinzu.
  3. Implementieren Sie Datenentführung (implementieren Sie die Beobachtungsmethode).

Der vollständige Code lautet wie folgt:

  Klasse Vue {
    // Empfange das übergebene Objekt Konstruktor(Optionen) {
      // Nützliche Informationen erhalten this.$el = document.querySelector(options.el);
      dies.$data = Optionen.data;

      // Container: {attribute1: [wathcer1, wathcer2...], attribute2: [...]}
      dies.$watcher = {};

      // Elemente analysieren: Implementieren von Compile
      this.compile(this.$el); // Um ​​das Element zu analysieren, müssen Sie das Element übergeben in // Daten kapern: Observer implementieren
      this.observe(this.$data); // Um ​​Daten zu kapern, müssen Sie die Daten übergeben}
    kompilieren(el) {
      // Analysieren Sie jeden untergeordneten Knoten unter dem Element, um el.children zu erhalten.
      // Erweiterung: children gibt einen Elementsatz zurück, childNodes gibt einen Knotensatz zurück let nodes = el.children;

      // Analysiere die Anweisungen für jeden untergeordneten Knoten for (var i = 0, length = nodes.length; i < length; i++) {
        sei Knoten = Knoten[i];
        // Wenn der aktuelle Knoten untergeordnete Elemente hat, den Knoten rekursiv analysieren, if (node.children) {
          dies.kompilieren(Knoten);
        }
        wenn (node.hasAttribute("v-text")) {
          let attrVal = node.getAttribute("v-text");
          // node.textContent = this.$data[attrVal]; 
          // Der Watcher ruft bei der Instanziierung „update“ auf und ersetzt diese Codezeile/**
           * Stellen Sie sich vor, welche Daten Wathcer zum Aktualisieren von Knotendaten verwenden muss? 
           * egpinnerHTML = vm.$data[msg]
           * Die zu übergebenden Parameter sind also: aktueller Knoten, zu aktualisierende Knotenattribute, Vue-Instanz, gebundene Datenattribute*/
          // Beobachter zum Container hinzufügen: {msg1: [Watcher, Watcher...], msg2: [...]}
          wenn (!this.$watcher[attrVal]) {
            dies.$watcher[attrVal] = [];
          }
          dies.$watcher[attrVal].push(neuer Watcher(Knoten, "innerHTML", dies, attrVal))
        }
        wenn (node.hasAttribute("v-model")) {
          let attrVal = node.getAttribute("v-Modell");
          Knoten.Wert = dies.$data[attrVal];

          node.addEventListener("Eingabe", (ev) => {
            dies.$data[attrVal] = ev.target.value;
          })

          wenn (!this.$watcher[attrVal]) {
            dies.$watcher[attrVal] = [];
          }
          // Anders als das oben verwendete innerHTML verwendet die Eingabe hier das Wertattribut this.$watcher[attrVal].push(new Watcher(node, "value", this, attrVal))
        }
      }
    }
    beobachten(Daten) {
      Objekt.Schlüssel(Daten).fürJeden((Schlüssel) => {
        let val = data[key]; // Dieser Wert wird immer im Speicher gespeichert. Jedes Mal, wenn Sie auf data[key] zugreifen, greifen Sie auf diesen Wert zu
        Object.defineProperty(Daten, Schlüssel, {
          erhalten() {
            return val; // Du kannst data[key] hier nicht direkt zurückgeben, sonst gerät es in eine Endlosschleife},
          setze(neuerWert) {
            wenn (Wert !== neuerWert) {
              val = newVal; // Ebenso kann data[key] hier nicht direkt gesetzt werden, was zu einer Endlosschleife führen würde this.$watcher[key].forEach((w) => {
                w.update();
              })
            }
          }
        })
      })
    }
  }

  Klasse Watcher {
    Konstruktor(Knoten, aktualisiertesAttr, vm, Ausdruck) {
      //Den übergebenen Wert speichern this.node = node;
      dies.updatedAttr = updatedAttr;
      dies.vm = vm;
      dieser.Ausdruck = Ausdruck;
      dies.update();
    }
    aktualisieren() {
      dieser.Knoten[dieses.updatedAttr] = diese.vm.$data[dieser.Ausdruck];
    }
  }

  lass vm = neues Vue({
    el: "#app",
    Daten: {
      Nachricht: "Hallo Welt",
      msg2: „hallo xiaofei“
    }
  })

An diesem Punkt ist der Code vollständig.

3. Zukunftspläne

Verwenden Sie das Wissen über Entwurfsmuster, um die Probleme im obigen Quellcode zu analysieren und ihn mit dem Vue-Quellcode zu vergleichen. Dies gilt als Analyse des Vue-Quellcodes.

Oben finden Sie den detaillierten Inhalt der Implementierungsmethode der bidirektionalen Vue-Datenbindung. Weitere Informationen zur bidirektionalen Vue-Datenbindung finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung des Implementierungsprinzips der bidirektionalen Datenbindung von Vue2.0/3.0
  • Analyse des Problems des Datenverlusts durch erzwungene Aktualisierung von Vuex
  • Wie verfolgt Vue Datenänderungen?
  • Vue + Canvas realisiert den Effekt der Aktualisierung des Wasserfalldiagramms von oben nach unten in Echtzeit (ähnlich wie QT).
  • Lösung für das Vue-Datenzuweisungsproblem
  • Vue setzt die Daten auf ihren ursprünglichen Zustand zurück
  • Analyse und Lösung von Datenverlusten während der Wertübertragung von Vue-Komponenten
  • SpringBoot + Vue realisiert die Funktion zum Hinzufügen von Daten
  • Beispiel für handschriftliches Vue2.0-Daten-Hijacking
  • Vermeiden Sie den Missbrauch zum Lesen von Daten in Vue
  • Entwerfen Sie einen Datensammler mit Vue

<<:  Detaillierte Erläuterung des Selinux-Grundkonfigurationstutorials unter Linux

>>:  Beispiel zum Erstellen eines lokalen Benutzers in MySQL und Erteilen von Datenbankberechtigungen

Artikel empfehlen

MySQL verwendet Binlog-Protokolle zur Implementierung der Datenwiederherstellung

MySQL Binlog ist ein sehr wichtiges Protokoll in ...

Nginx definiert die Zugriffsmethode für Domänennamen

Ich erstelle derzeit Nginx, kann aber nicht über ...

Zusammenfassung mehrerer APIs oder Tipps in HTML5, die Sie nicht verpassen sollten

In früheren Blogbeiträgen habe ich mich auf einige...

Detaillierte Erklärung der CocosCreator MVC-Architektur

Überblick Dieser Artikel stellt die in Spieleclie...

So führen Sie Hadoop aus und erstellen Images in Docker

Wir erfinden das Rad neu: Hier verwenden wir Neuv...

Einfaches HTML-Applet für Einkaufsmengen

Dieser Artikel stellt Ihnen ein einfaches HTML-Ap...

CentOS 6.5 Installations-Tutorial zu MySQL 5.7

1. Neue Funktionen MySQL 5.7 ist ein spannender M...

Vue einfache Implementierung einer Plattenspielerlotterie

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

Das Prinzip und die Anwendung der ES6-Dekonstruktionszuweisung

Inhaltsverzeichnis Array-Destrukturierungszuweisu...

Mit CSS3 lässt sich ein umdrehbarer Hover-Effekt erzielen

CSS3 implementiert einen umdrehbaren Hover-Effekt...

CSS-Anfänger-Tutorial: Hintergrundbild füllt den gesamten Bildschirm

Wenn Sie möchten, dass die gesamte Benutzeroberfl...

Detaillierte Erklärung der Slots in Vue

Die Wiederverwendung von Code in Vue liefert uns ...