Vue verwendet die Methode https://jsrun.net/RMIKp/embedded/all/light Das MVVM-Framework umfasst hauptsächlich zwei Aspekte: Aktualisieren der Ansicht, wenn sich die Daten ändern, und Aktualisieren der Daten, wenn sich die Ansicht ändert. Die Ansicht ändert und aktualisiert die Daten. Wenn es sich um ein Tag wie „Input“ handelt, können Sie Um die Ansicht zu aktualisieren, wenn sich Daten ändern, können Sie die 1. Implementierungsprozess Nachdem wir nun wissen, wie die bidirektionale Bindung implementiert wird, müssen wir zunächst die Daten entführen und überwachen. Daher müssen wir eine Ändert sich die Eigenschaft, muss der Abonnenten Außerdem ist eine Direktiveparser- Der Ablauf sieht also vermutlich so aus:
2. Zeigen Sie einen Beobachter an var Bibliothek = { Buch1: { Name: "", }, Buch2: "", }; beobachten (Bibliothek); library.book1.name = "vue authoritative guide"; // Der Eigenschaftsname wurde überwacht und der aktuelle Wert ist: "vue authoritative guide" library.book2 = „Kein solches Buch“; // Das Attribut book2 wurde überwacht und der aktuelle Wert ist: „Kein solches Buch“ //Erkennungsfunktion für Daten hinzufügen defineReactive(data, key, val) { observe(val); // Alle Unterattribute rekursiv durchlaufen let dep = new Dep(); // Ein neues Dep erstellen Object.defineProperty(Daten, Schlüssel, { aufzählbar: wahr, konfigurierbar: true, bekomme: Funktion() { wenn (Dep.target) { // Bestimmen Sie, ob ein Abonnent hinzugefügt werden soll. Dies ist nur beim ersten Mal erforderlich und nicht beim nächsten Mal. Einzelheiten finden Sie in der Watcher-Funktion dep.addSub(Dep.target); // Einen Abonnenten hinzufügen } Rückgabewert; }, setze: Funktion(neuerWert) { if (val == newVal) return; // zurück, wenn sich der Wert nicht geändert hat val = neuerWert; konsole.log( "Property" + key + " wurde überwacht und der aktuelle Wert ist: "" + newVal.toString() + """ ); dep.notify(); // Wenn sich die Daten ändern, alle Abonnenten benachrichtigen. }, }); } // Alle Eigenschaften des Monitoring-Objekts function observe(data) { wenn (!Daten || Datentyp !== "Objekt") { return; // Wenn es kein Objekt ist, returniere } Objekt.Schlüssel(Daten).fürJeden(Funktion(Schlüssel) { defineReactive(Daten, Schlüssel, Daten[Schlüssel]); }); } // Dep ist für das Sammeln von Abonnenten und das Auslösen der Aktualisierungsfunktion verantwortlich, wenn sich die Eigenschaft ändert. Funktion Dep() { dies.subs = {}; } Dep.prototype = { addSub: Funktion(sub) { dies.subs.push(sub); }, benachrichtigen: function() { Dies.subs.forEach((sub) => sub.update()); }, }; Bei der Ideenanalyse muss ein Abonnenten-Dep vorhanden sein, das Abonnentennachrichten aufnehmen kann, zum Sammeln von Abonnenten und zum Ausführen der entsprechenden Aktualisierungsfunktion dient, wenn sich die Attribute ändern. Aus dem Code geht hervor, dass das Hinzufügen des Abonnenten-Dep im Wenn sich im Bisher wurde ein relativ vollständiger 3. Implementieren Sie Watcher Der Abonnenten Wie lösen Sie also „Get“ aus? Da wir Wir müssen den Abonnenten nur auf Dep.target zwischenspeichern, wenn der Abonnenten-Watcher initialisiert wird, und ihn nach erfolgreichem Hinzufügen entfernen. Funktion Watcher(vm, exp, cb) { dies.cb = cb; dies.vm = vm; dies.exp = exp; this.value = this.get(); // Fügen Sie sich selbst zur Operation des Abonnenten hinzu} Watcher.Prototyp = { aktualisieren: Funktion() { dies.laufen(); }, ausführen: function() { var-Wert = this.vm.data[this.exp]; var alterWert = dieser.Wert; wenn (Wert !== alterWert) { dieser.Wert = Wert; this.cb.call(this.vm, Wert, alterWert); } }, bekomme: Funktion() { Dep.target = this; // Cache selbst, um zu bestimmen, ob ein Watcher hinzugefügt werden soll. var value = this.vm.data[this.exp]; // Erzwinge die Ausführung der Get-Funktion im Listener Dep.target = null; // Befreie dich selbst return value; }, }; Bisher ist das einfache Da die Parser- Konvertieren Sie den Code in einen ES6-Konstruktor und zeigen Sie eine Vorschau an. https://jsrun.net/8SIKp/embed... Da dieser Code keinen Compiler implementiert, sondern die gebundenen Variablen direkt übergibt, legen wir zur Bindung nur Daten ( Und nehmen Sie die Änderungen nach zwei Sekunden vor. Sie können sehen, dass sich auch die Seite geändert hat. // MyVue ProxyKeys(Schlüssel) { var selbst = dies; Object.defineProperty(dieser, Schlüssel, { aufzählbar: falsch, konfigurierbar: true, erhalten: Funktion ProxyGetter() { gibt self.data[Schlüssel] zurück; }, set: Funktion ProxySetter(neuerWert) { self.data[Schlüssel] = neuerWert; } }); } Der Zweck des obigen Codes besteht darin, den Schlüssel von 4. Implementieren Sie CompileObwohl oben eine bidirektionale Datenbindung implementiert ist, werden die DOM-Knoten während des gesamten Prozesses nicht analysiert, sondern fest ersetzt. Daher ist ein Parser erforderlich, um die Daten zu analysieren und zu binden. Implementierungsschritte der Parser
Um die Vorlage zu analysieren, müssen Sie zuerst die DOM-Daten analysieren und dann die entsprechenden Anweisungen für die DOM-Elemente verarbeiten. Daher ist der gesamte DOM-Vorgang relativ häufig. Sie können ein neues Fragment erstellen und das erforderliche analysierte Funktion nodeToFragment(el) { var fragment = document.createDocumentFragment(); var Kind = el.erstesKind; während (Kind) { // Verschiebe das Dom-Element in das Fragment fragment.appendChild(child); Kind = el.erstesKind; } Fragment zurückgeben; } Als Nächstes müssen Sie jeden Knoten durchlaufen und eine spezielle Verarbeitung an den Knoten durchführen, die relevante Anweisungen und Vorlagensyntax enthalten. Führen Sie zunächst die einfachste Vorlagensyntaxverarbeitung durch und verwenden Sie reguläre Ausdrücke, um die Syntax in der Form „{{variable}}“ zu analysieren. Funktion KompilierenElement (el) { var childNodes = el.childNodes; var selbst = dies; [].slice.call(childNodes).forEach(Funktion(Knoten) { var reg = /\{\{(.*)\}\}/; // entspricht {{xx}} var text = node.textinhalt; if (self.isTextNode(node) && reg.test(text)) { // Bestimme, ob es sich um eine Anweisung dieser Form handelt {{}} self.compileText(node, reg.exec(text)[1]); } wenn (node.childNodes && node.childNodes.length) { self.compileElement(node); //Weiter mit dem rekursiven Durchlaufen der untergeordneten Knoten} }); }, Funktion KompilierenText (Knoten, Ausdruck) { var selbst = dies; var initText = this.vm[exp]; updateText(node, initText); // Initialisiere die initialisierten Daten in der Ansicht new Watcher(this.vm, exp, function (value) { // Generiere einen Abonnenten und binde die Update-Funktion self.updateText(node, value); }); }, Funktion updateText (Knoten, Wert) { node.textContent = Typ des Wertes == ‚undefiniert‘?‘‘: Wert; } Rufen Sie nach dem Abrufen des äußersten Knotens Anschließend müssen Sie für die aktuellen Parameter einen entsprechenden Abonnenten der Aktualisierungsfunktion generieren, um bei einer Datenänderung das entsprechende DOM zu aktualisieren. Damit sind die drei Prozesse Parsen, Initialisieren und Kompilieren abgeschlossen. Ändern Sie als Nächstes myVue, um Vorlagenvariablen für die bidirektionale Datenbindung zu verwenden. https://jsrun.net/K4IKp/embed... 5. Fügen Sie Analyseereignisse hinzu Nach dem Hinzufügen von Fügen Sie ein V-Modell und eine V-On-Analyse hinzu: Funktion Kompilieren(Knoten) { var nodeAttrs = node.attributes; var selbst = dies; Array.prototype.forEach.call(nodeAttrs, Funktion(attr) { var attrName = attr.name; wenn (istDirektive(attrName)) { var exp = attr.Wert; var dir = attrName.substring(2); if (isEventDirective(dir)) { // Ereignisanweisung self.compileEvent(node, self.vm, exp, dir); } anders { // v-model-Direktive self.compileModel(node, self.vm, exp, dir); } node.removeAttribute(attrName); // Analyse abgeschlossen, Attribut entfernen} }); } // v-Direktive-Analysefunktion isDirective(attr) { return attr.indexOf("v-") == 0; } // ein: Direktive-Analysefunktion isEventDirective(dir) { return dir.indexOf("on:") === 0; } Die obige 6. Vollversion von myVue Fügen Sie in Klasse MyVue { Konstruktor(Optionen) { var selbst = dies; diese.Daten = Optionen.Daten; diese.Methoden = Optionen.Methoden; Object.keys(diese.Daten).forEach(Funktion(Schlüssel) { self.proxyKeys(Schlüssel); }); beobachte(diese.Daten); neues Kompilieren(options.el, this); options.mounted.call(this); //Führen Sie die gemountete Funktion aus, nachdem alles erledigt ist} ProxyKeys(Schlüssel) { // Proxy this.data-Eigenschaft an diese Variable self = this; Object.defineProperty(dieser, Schlüssel, { aufzählbar: falsch, konfigurierbar: true, erhalten: Funktion Getter () { gibt self.data[Schlüssel] zurück; }, set: Funktion Setter(neuerWert) { self.data[Schlüssel] = neuerWert; }, }); } } Dann kannst Du es testen. https://jsrun.net/Y4IKp/embed... Fassen wir den Vorgang zusammen. Wenn Sie sich dieses Diagramm noch einmal ansehen, ist es jetzt viel klarer. Sie können die Codeadresse anzeigen: Vue2.x-Zwei-Wege-Bindungsprinzip und -Implementierung Dies ist das Ende dieses Artikels über das Zwei-Wege-Bindungsprinzip und die Implementierung von Das könnte Sie auch interessieren:
|
<<: Analyse der Prinzipien der MySQL Slow Query-bezogenen Parameter
>>: Eine kurze Diskussion über die MySQL-Optimierungslösung für große Tabellen
Laden Sie zuerst die Abhängigkeiten herunter Garn...
Dieser Artikel stellt einige Aspekte von HTML-Tag...
Die Fremdschlüsseleinschränkung von MySQL dient z...
Beim Absenden eines Formulars kann es vorkommen, d...
Das Seitenlayout war mir schon immer ein Anliegen...
MySQL 8.0.22 Download-, Installations- und Konfig...
Inhaltsverzeichnis Transaktionsisolationsebene Wa...
Viele Leute sagen, dass IE6 PNG-Transparenz nicht...
Inhaltsverzeichnis Einführung Anweisungen Tatsäch...
Es gibt einen Tabellenbenutzer und die Felder sin...
Das MySQL-Entwicklungsteam hat am 14. Oktober 201...
Einführung in Dockerfile Docker kann automatisch ...
Lassen Sie mich zunächst über meinen Alltag sprec...
1. Speicher-Engine Im letzten Abschnitt haben wir...
Amtliche Dokumentation: https://dev.mysql.com/doc...