In diesem Artikel wird anhand des folgenden Beispiels der Vorgang der berechneten Initialisierung und Aktualisierung erläutert und gezeigt, wie die berechneten Eigenschaften zwischengespeichert und die Abhängigkeiten erfasst werden. <div id="app"> <span @click="change">{{sum}}</span> </div> <script src="./vue2.6.js"></script> <Skript> neuer Vue({ el: "#app", Daten() { zurückkehren { Anzahl: 1, } }, Methoden: { ändern() { diese.Anzahl = 2 }, }, berechnet: { Summe() { gib dies zurück.Anzahl + 1 }, }, }) </Skript> Berechnete Daten initialisierenWenn vue initialisiert wird, wird zuerst die Init-Methode ausgeführt, und der darin enthaltene InitState initialisiert die berechneten Eigenschaften wenn (opts.computed) {initComputed(vm, opts.computed);} Unten ist der Code für initComputed var watchers = vm._computedWatchers = Object.create(null); // Definieren Sie nacheinander einen berechneten Beobachter für jede berechnete Eigenschaft für (const Schlüssel in berechnet) { const userDef = berechnet[Schlüssel] Beobachter[Schlüssel] = neuer Beobachter( vm, // Instanzgetter, // vom Benutzer übergebene Auswertungsfunktion sum noop, // Callback-Funktion kann zunächst ignoriert werden { lazy: true } // Lazy-Attribut deklarieren um berechneten Watcher zu markieren ) // Was passiert, wenn der Benutzer this.sum defineComputed(vm, key, userDef) aufruft? } Der Anfangszustand des Berechnungs-Watchers entsprechend jeder berechneten Eigenschaft ist wie folgt: { abhängig von: [], schmutzig: wahr, Getter: ƒ sum(), faul: stimmt, Wert: undefiniert } Sie können sehen, dass sein Wert am Anfang nicht definiert ist und „lazy“ „true“ ist, was bedeutet, dass sein Wert verzögert berechnet wird und erst berechnet wird, wenn sein Wert tatsächlich in der Vorlage gelesen wird. Dieses Dirty-Attribut ist tatsächlich der Schlüssel zum Caching, also merken Sie es sich zuerst. Als nächstes schauen wir uns das kritischere defineComputed an, das bestimmt, was passiert, nachdem der Benutzer den Wert der berechneten Eigenschaft this.sum gelesen hat. Wir werden weiterhin einige Logik vereinfachen und ausschließen, die den Prozess nicht beeinflusst. Object.defineProperty(Ziel, Schlüssel, { erhalten() { // Den berechneten Watcher von der gerade erwähnten Komponenteninstanz holen const watcher = this._computedWatchers && this._computedWatchers[Schlüssel] wenn (Beobachter) { // Nur wenn es schmutzig ist, wird es neu ausgewertet, wenn (watcher.dirty) { // Dadurch wird get ausgewertet, aufgerufen und Dep.target festgelegt. Beobachter.auswerten() } // Auch das ist ein wichtiger Punkt und ich werde ihn später im Detail erklären if (Dep.target) { Beobachter.abhängig() } //Zum Schluss den berechneten Wert zurückgeben return watcher.value } } }) Diese Funktion muss genauer betrachtet werden. Sie macht mehrere Dinge. Lassen Sie es uns anhand des Initialisierungsprozesses erklären: Zunächst einmal stellt das Konzept „Dirty“ schmutzige Daten dar, was bedeutet, dass die Daten durch erneuten Aufruf der vom Benutzer übergebenen Summenfunktion ausgewertet werden müssen. Lassen wir die Update-Logik vorerst einmal außer Acht. Beim ersten Lesen von {{sum}} in der Vorlage muss es wahr sein, damit die Initialisierung eine Auswertung durchläuft. auswerten() { //Rufen Sie die Get-Funktion auf, um this.value = this.get() auszuwerten //Dirty als falsch markieren this.dirty = falsch } Diese Funktion ist eigentlich sehr übersichtlich, sie wertet zuerst aus und setzt dann „dirty“ auf „false“. Schauen wir uns noch einmal die Logik von Object.defineProperty an. Wenn das nächste Mal die Summe ohne besondere Umstände gelesen wird und dirty falsch ist, können wir einfach den Wert von watcher.value zurückgeben. Dies ist eigentlich das Konzept des berechneten Eigenschafts-Cachings. AbhängigkeitssammlungNach Abschluss der Initialisierung wird Render zum Rendern aufgerufen, und die Renderfunktion dient als Getter des Watchers. Zu diesem Zeitpunkt ist der Watcher der Rendering-Watcher. updateComponent = () => { vm._update(vm._render(), hydratisieren) } // Rendering-Watcher erstellen. Wenn der Rendering-Watcher initialisiert wird, wird seine get()-Methode, also die Render-Funktion, aufgerufen, um Abhängigkeiten zu sammeln new Watcher(vm, updateComponent, noop, {}, true /* isRenderWatcher */) Schauen Sie sich die Get-Methode im Watcher an. erhalten () { //Lege den aktuellen Watcher ganz oben auf den Stapel und setze ihn auf Dep.target drückeZiel(dieses) let-Wert const vm = diese.vm // Durch Aufrufen der benutzerdefinierten Funktion wird auf this.count zugegriffen und damit auf die Getter-Methode, die weiter unten erläutert wird. value = this.getter.call(vm, vm) // Nachdem die Auswertung abgeschlossen ist, wird der aktuelle Watcher aus dem Stack entfernt popTarget() dies.cleanupDeps() Rückgabewert } Wenn der Getter des Rendering-Watchers ausgeführt wird (Renderfunktion), wird auf this.sum zugegriffen, wodurch der Getter des berechneten Attributs ausgelöst wird, d. h. die in initComputed definierte Methode. Nachdem der berechnete Watcher an die Summe gebunden wurde, wird seine Auswertungsmethode aufgerufen, da dirty während der Initialisierung true ist, und schließlich wird seine Methode get() aufgerufen, um den berechneten Watcher oben auf dem Stapel abzulegen. Zu diesem Zeitpunkt ist Dep.target auch der berechnete Watcher. Wenn Sie dann die Get-Methode aufrufen, wird auf this.count zugegriffen, wodurch der Getter des Count-Attributs ausgelöst wird (wie unten gezeigt) und der im aktuellen Dep.target gespeicherte Watcher in der dem Count-Attribut entsprechenden Dep gesammelt wird. An diesem Punkt ist die Auswertung abgeschlossen und popTarget() wird aufgerufen, um den Watcher aus dem Stapel zu entfernen. An diesem Punkt befindet sich der vorherige Rendering-Watcher ganz oben auf dem Stapel und Dep.target wird wieder zum Rendering-Watcher. // Im Abschluss wird das für die Schlüsselanzahl definierte Dep beibehalten const dep = new Dep() // Der Abschluss behält auch den von der letzten Set-Funktion festgelegten Wert bei lass val Objekt.defineProperty(Objekt, Schlüssel, { get: Funktion reactiveGetter () { konstanter Wert = val // Dep.target berechnet nun den Watcher wenn (Dep.target) { // Abhängigkeiten sammeln dep.depend() } Rückgabewert }, }) // dep.abhängig() abhängen() { wenn (Dep.target) { Dep.target.addDep(dieses) } } // addDep-Funktion des Beobachters addDep (dep: Dep) { // Zur Vereinfachung werden hier eine Reihe von Deduplizierungsvorgängen durchgeführt // Hier wird die Dep von count auch in ihren eigenen Deps gespeichert this.deps.push(dep) // Mit dem Watcher selbst als Parameter // Zurück zur addSub-Funktion von dep dep.addSub(this) } Klasse Dep { subs = [] addSub (sub: Beobachter) { dies.subs.push(sub) } } Durch diese beiden Codeteile wird der berechnete Watcher durch das Attribut Bound Dep gesammelt. Der Watcher hängt vom Dep ab und das Dep hängt auch vom Watcher ab. Diese voneinander abhängige Datenstruktur kann leicht erkennen, von welchen Deps ein Watcher abhängt und von welchen Watchern ein Dep abhängt. Führen Sie dann watcher.depend() aus // Beobachter.abhängig abhängen() { sei i = this.deps.length während (i--) { dies.deps[i].depend() } } Erinnern Sie sich an die Berechnung des Beobachterformulars von gerade eben? Seine Abhängigkeiten speichern die Abhängigkeit der Anzahl. Das heißt, dep.depend() wird bei count erneut aufgerufen. Klasse Dep { subs = [] abhängen() { wenn (Dep.target) { Dep.target.addDep(dieses) } } } Dieses Mal ist Dep.target bereits der Rendering-Watcher, sodass das Dep dieser Zählung den Rendering-Watcher in seinen eigenen Subs speichert. Schließlich werden die Abhängigkeiten von count gesammelt und ihre Abhängigkeit lautet: { Subs: [Summenberechnungs-Beobachter, Rendering-Beobachter] } Updates verteilenNun kommen wir zum Kernpunkt dieser Frage: Wie wird die Ansichtsaktualisierung ausgelöst, wenn der Zähler aktualisiert wird? Kehren wir zur responsiven Hijacking-Logik von count zurück: // Im Abschluss wird das für die Schlüsselanzahl definierte Dep beibehalten const dep = new Dep() // Der Abschluss behält auch den von der letzten Set-Funktion festgelegten Wert bei lass val Objekt.defineProperty(Objekt, Schlüssel, { set: Funktion reactiveSetter (newVal) { val = neuerWert // Benachrichtigung über die Abhängigkeit des Zählers auslösen dep.benachrichtigen() } }) }) Nun, hier wird die Benachrichtigungsfunktion des Count-Dep ausgelöst, die wir gerade sorgfältig vorbereitet haben. Klasse Dep { subs = [] benachrichtigen () { für (sei i = 0, l = Teillänge; i < l; i++) { subs[i].update() } } } Die Logik hier ist sehr einfach. Rufen Sie nacheinander die Update-Methode der in Subs gespeicherten Watcher auf, d. h.
Berechnen von Watcher-Updates aktualisieren () { wenn (dies.lazy) { dies.schmutzig = wahr } } Setzen Sie einfach die Dirty-Eigenschaft des Berechnungsbeobachters auf „true“ und warten Sie ruhig auf den nächsten Lesevorgang (wenn die Renderfunktion erneut ausgeführt wird, wird erneut auf die Summeneigenschaft zugegriffen und „Dirty“ ist zu diesem Zeitpunkt „true“, sodass es erneut ausgewertet wird). Aktualisierungen des Rendering-Watchers Hier rufen wir tatsächlich die Funktion vm._update(vm._render()) auf, um die Ansicht entsprechend dem von der Renderfunktion generierten Vnode erneut zu rendern. Object.defineProperty(Ziel, Schlüssel, { erhalten() { const watcher = this._computedWatchers && this._computedWatchers[Schlüssel] wenn (Beobachter) { // Im vorherigen Schritt wurde dirty bereits auf true gesetzt, daher wird es erneut ausgewertet, wenn (watcher.dirty) { Beobachter.auswerten() } wenn (Dep.target) { Beobachter.abhängig() } //Zum Schluss den berechneten Wert zurückgeben return watcher.value } } }) Aufgrund der reaktionsfähigen Eigenschaftsaktualisierung im vorherigen Schritt wird das Dirty Update des berechneten Watchers auf „True“ ausgelöst. Daher wird die vom Benutzer übergebene Summenfunktion erneut aufgerufen, um den neuesten Wert zu berechnen, und der neueste Wert wird natürlich auf der Seite angezeigt. Damit ist der gesamte Prozess der Berechnung von Attributaktualisierungen abgeschlossen. Um zusammenzufassen
Oben finden Sie eine ausführliche Erläuterung des Cache-Implementierungsprinzips von Vue Computed. Weitere Informationen zur Cache-Implementierung von Vue Computed finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: Tutorial zur Installation und Konfiguration der dekomprimierten Version von mysql5.7.19 winx64
>>: Verwaltung privater Docker-Repositorys und Löschen von Bildern in lokalen Repositorys
Lassen Sie mich zunächst eine interessante Eigens...
Inhaltsverzeichnis 1. Übersicht 1.1 Was ist ein P...
1. Dreieck Rahmeneinstellungen Code: Breite: 300p...
Dieses Projekt teilt den spezifischen Code von Vu...
In CSS-Dateien sehen wir oft, dass einige Schrift...
Der Textarea-Tag ist ein HTML-Tag, den wir häufig ...
1. Herunterladen https://dev.mysql.com/downloads/...
Referenz: Offizielle Docker-Redis-Dokumentation 1...
Inhaltsverzeichnis 1. Schloss und Riegel 2. Wiede...
Hintergrund Der Unternehmenscode wird Dritten zur...
1. Analytisches Denken 1. Beseitigen Sie die eige...
1. Vorbereitung Middleware: Tomcat, Redis, Nginx ...
Inhaltsverzeichnis Replikationsarchitektur mit ei...
Von der Entwicklung bis zur Bereitstellung: Mache...
Das Shell-Skript richtet die Zugriffskontrolle ei...