Heim  >  Artikel  >  Web-Frontend  >  Was ist das Prinzip der Vue-Reaktionsfähigkeit? Analyse des Vue-Responsivitätsprinzips

Was ist das Prinzip der Vue-Reaktionsfähigkeit? Analyse des Vue-Responsivitätsprinzips

不言
不言Original
2018-09-10 15:33:512601Durchsuche

In diesem Artikel erfahren Sie, was das Prinzip der Vue-Reaktionsfähigkeit ist. Die Analyse des Reaktionsfähigkeitsprinzips von Vue hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen.

initState

new Vue() => Rufen Sie die entsprechende Initialisierungsfunktion auf

initProps und initData

Die Hauptaufgabe besteht darin Rufen Sie defineProperty auf, um get für die jeweiligen Eigenschaften zu mounten (wenn dieser Hook ausgelöst wird, wird die Dep der aktuellen Eigenschaft verwendet). Die Instanz wird in das aktuelle Dep.target verschoben, das die Deps des aktuellen Watchers ist, also die Abhängigkeiten davon Das Abonnieren von Dep.target wird weiter unten besprochen, und die Dep-Instanz schiebt auch den aktuellen Beobachter, d. .

initComputed

Seine Funktion besteht darin, alle Eigenschaften im berechneten Objekt zu durchlaufen und der Eigenschaft einen neuen berechneten Beobachter zu geben (in der berechneten Eigenschaft ist eine Abhängigkeit definiert). Abonnieren Sie den Beobachter, der die berechnete Eigenschaft verwenden muss. Außerdem werden die Get- (Get-Methode) und die Set-Methode durch Aufrufen von defineProperty auf „Computed“ gemountet (die Set-Methode bestimmt, ob sie übergeben wird, und wenn sie nicht übergeben wird, wird sie auf eine leere Noop-Funktion gesetzt) ​​

Die get-Methode des berechneten Attributs ist der Rückgabewert der folgenden Funktion: Funktion

function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

Achten Sie auf watcher.depend(). Diese Methode ermöglicht es dem Watcher-Beobachter, der dieses Attribut verwendet, die Abhängigkeit zu abonnieren Der Beobachter und der Beobachter des berechneten Attributs schieben den Beobachter, der ihn abonniert hat, in seine In-Subs (wenn sich der berechnete Attributwert ändert, benachrichtigen Sie den Beobachter, der ihn abonniert hat) watcher.evaluate(), diese Methode wird durch Aufrufen des Get-Methode des Watchers (es ist zu beachten, dass die Get-Methode des Watchers pushTarget aufruft. Schieben Sie die vorherige Dep.target-Instanz auf den Stapel und stellen Sie Dep.target auf die Berechnung ein Beobachter, die reagierende Eigenschaft, von der die berechnete Eigenschaft abhängt, wird sein Der Beobachter wird in seine Subs verschoben. Wenn sich also die abhängige Antworteigenschaft ändert, wird der berechnete Beobachter, der ihn abonniert, benachrichtigt, der berechnete Beobachter Benachrichtigen Sie dann den Beobachter, der das berechnete Attribut abonniert hat, um die Aktualisierungsmethode aufzurufen, und rufen Sie die an den berechneten Attributschlüssel gebundene Handlerfunktion in der get-Methode auf, um den Wert zu berechnen.


initWatch

Dieser Watcher ist ein Benutzer-Watcher (vom Entwickler in der Komponente angepasst).

Die Funktion von initWatch besteht darin, die Eigenschaften in der Uhr zu durchlaufen und die definierte $watch für jede von der Uhr überwachte Eigenschaft aufzurufen

function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      watcher.depend()
      return watcher.evaluate()
    }
  }
}

Wenn ein neuer Watcher im Code aufgerufen wird, wird der Watcher genauso ausgeführt Render-Watcher. Die get-Methode ruft pushTarget auf, um den aktuellen Benutzer-Watcher Dep.target zuzuweisen. Die Anweisung value = this.getter.call(vm, vm) in get() löst die get-Methode des vom Benutzer überwachten responsiven Attributs aus Beobachter und Ändern Sie den aktuellen Benutzer Der Watcher schiebt in die Subs, von denen dieses Attribut abhängt, also wenn der Benutzer Nachdem der vom Watcher überwachte Eigenschaftssatz ausgelöst wurde, wird der Watcher, der die Abhängigkeit abonniert hat, benachrichtigt, um die Aktualisierung auszulösen, dh der Handler, der dem an die Watch gebundenen Schlüssel entspricht, wird ausgelöst. Rufen Sie dann popTarget auf, um den Stapel zu öffnen und ihn Dep.target zuzuweisen.

$mount

Die initState-Initialisierungsarbeit ist hier grob abgeschlossen, und dann wird $mount ausgeführt, um die Rendering-Arbeit zu starten

Die Hauptarbeit von $mount: Erstellen eines neuen Rendering-Watchers und verwenden Sie updateCompent als Rückruf. Wenn Sie es übergeben und

Vue.prototype.$watch = function (
    expOrFn: string | Function,
    cb: any,
    options?: Object
  ): Function {
    const vm: Component = this
    if (isPlainObject(cb)) {
      return createWatcher(vm, expOrFn, cb, options)
    }
    options = options || {}
    options.user = true // 代表该watcher是用户自定义watcher
    const watcher = new Watcher(vm, expOrFn, cb, options)
    if (options.immediate) {
      cb.call(vm, watcher.value)
    }
    return function unwatchFn () {
      watcher.teardown()
    }
  }

new Watcher unter den drei Watchern ausführen, führt nur der berechnete Watcher seine get()-Methode zu Beginn nicht aus. Der neue Render-Watcher in $mount ruft die Methode get() und pushTarget auf, um Dep.target den aktuellen Render-Watcher zuzuweisen. Als nächstes kommt der Höhepunkt, der Aufruf von updateComponent, der vm._update(vm._render(), hydrating) ausführt, wobei die Renderfunktion den Get-Hook der in HTML verwendeten responsiven Attribute auslöst. Der Get-Hook bewirkt, dass die abhängige Instanz-Dep der responsiven Eigenschaft das aktuelle Rendering konvertiert Der Watcher wird in sein Subs-Array verschoben. Wenn sich also die abhängigen Antworteigenschaften ändern, durchläuft er die Subs, um den Watcher, der ihn abonniert hat, zu benachrichtigen, update() aufzurufen.

Beispiel

Vielleicht sind Sie verwirrt darüber, wie Sie Watcher und Dep anpassen sollen. Lassen Sie mich Ihnen ein Beispiel geben.

updateComponent = () => {
      vm._update(vm._render(), hydrating)
    }
new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted) {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)

Ich werde direkt mit dem Rendern beginnen und nur über Dep sprechen und dep. Watcher-bezogen

$mount: neu wird ein Rendering-Watcher (die Get-Methode des Watchers weist den Rendering-Watcher Dep.target zu) beim Rendern ausgelöst Im obigen Beispiel wird a zuerst verwendet. Zu diesem Zeitpunkt wird der Get-Hook von a ausgelöst. Unter anderem wird dep.depend() den aktuellen Rendering-Watcher in das Sub-Array von dep verschieben das a-Attribut.


Fahren Sie mit der Ausführung fort und greifen Sie auf b zu (b ist der Wert des berechneten Attributs), wodurch die Get-Methode des berechneten Attributs ausgelöst wird. Die get-Methode der berechneten Eigenschaften ist die zurückgegebene Funktion „computedGetter“, nachdem die Funktion „createComputedGetter“ aufgerufen wurde. „watcher.depend()“ wird in der Funktion „computedGetter“ ausgeführt. Die Abhängigkeitsmethode von Watcher ist ausschließlich der Berechnung vorbehalten Wird vom Beobachter verwendet.

Wie oben erwähnt, sind zusätzlich zum berechneten Watcher die beiden anderen Watcher neu Danach werden ihre Get-Methoden ausgeführt und dann berechnet Was macht der Beobachter, nachdem die neue Dep abgeschlossen ist?

Gehen Sie zurück zur Methode watcher.depend(), die gerade für den berechneten Watcher erwähnt wurde. Ihre Funktion besteht darin, this.dep.depend() auszuführen (hier wird die durch den berechneten Watcher definierte Abhängigkeit verwendet). this.dep.depend() bewirkt, dass der aktuelle Rendering-Watcher die berechnete Eigenschaftsabhängigkeit abonniert. Die berechnete Eigenschaft verschiebt den Rendering-Watcher auch in seine eigenen Subs ([Render-Watcher]), wenn der Wert der berechneten Eigenschaft geändert wird , wird der Beobachter in Subs benachrichtigt, update() aufzurufen, damit die Seite aktualisiert werden kann, wenn sich der berechnete Attributwert ändert.

Gehen Sie zurück zum Get-Hook, der das berechnete Attribut von b ausgelöst hat. Der Get-Hook führt schließlich watcher.evaluate() aus und watcher.evaluate() führt die get()-Methode des berechneten Watchers aus.

Der entscheidende Punkt kommt zu diesem Zeitpunkt: Dep.target (Render-Watcher) wird in den TargetStack-Stapel verschoben (nachdem es gespeichert wurde, damit es später zur weiteren Verwendung herausgenommen werden kann) und dann der berechnete Watcher Dieses berechnete Attribut wird Dep .target zugewiesen. In der get-Methode führt value = this.getter.call(vm, vm) den an das berechnete Attribut gebundenen Handler aus.

Geben Sie a + 1 wie im obigen Beispiel zurück. Wenn a verwendet wird, wird der get-Hook von a ausgelöst und der get-Hook ruft dep.depend() auf, wodurch der berechnete Watcher dep in seinem deps-Array speichert und a's dep die aktuelle dep speichert . Dep.target (berechneter Watcher) wird in seinem Subs-Array gespeichert. Im aktuellen Beispiel werden die Subs von a [Render Watcher, Computed Watcher] sein, sodass Änderungen im Wert von a die Watcher in den Subs von a durchlaufen und rufen Sie die update()-Methode auf. Das in HTML verwendete a wird aktualisiert. Wenn der berechnete Attribut-Watcher die update()-Methode aufruft, benachrichtigt er seine eigenen Subs ([render watcher]) in render Wenn der Beobachter die Update-Methode aufruft, aktualisiert das in HTML verwendete berechnete Attribut b den Dom (zur Erinnerung, ich spreche nur grob, es wird nicht unbedingt eine Aktualisierung nach dem Attribut auslösen, dass das berechnete Attribut von Änderungen abhängt, das wird es tun). Vergleichen Sie nach Abschluss der Berechnung, ob sich der Wert ändert).

berechnet Die get()-Methode des Watchers ruft schließlich popTarget() auf, entfernt den zuvor gespeicherten Render-Watcher aus dem Stapel und weist ihn Dep.target zu. Zu diesem Zeitpunkt wird der targetStack in meinem Beispiel zu einem leeren Array.

Die Get-Methode des Render-Watchers wird am Ende der Ausführung vom Stapel entfernt. Zu diesem Zeitpunkt ist der Dep.target zugewiesene Wert leer.

Verwandte Empfehlungen:

Vue-Daten-Responsivitätsprinzip-Analyse

Über Responsivitätsprinzipien in Vue (ausführliches Tutorial)


Das obige ist der detaillierte Inhalt vonWas ist das Prinzip der Vue-Reaktionsfähigkeit? Analyse des Vue-Responsivitätsprinzips. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn