Heim  >  Artikel  >  Web-Frontend  >  Was ist das Responsivitätsprinzip von Vue?

Was ist das Responsivitätsprinzip von Vue?

醉折花枝作酒筹
醉折花枝作酒筹nach vorne
2021-07-29 17:42:192999Durchsuche

Ich habe in letzter Zeit viele Artikel über Vue-Prinzipien gelesen. Mithilfe dieser Artikel habe ich viele Male versucht, den Quellcode von Vue selbst zu verstehen. Abschließend denke ich, dass es an der Zeit ist, den Inhalt selbst auszugeben. Ich hoffe, dass ich jeden aus einer anderen Perspektive als andere Artikel mit Vue vertraut machen kann. Die Bedeutung von

Was ist das Responsivitätsprinzip von Vue?

Dep

var Dep = function Dep() {
  this.id = uid++
  this.subs = []
}

Dep ist natürlich Abhängigkeit (d. h. Abhängigkeit, ein Substantiv im Computerbereich).

Genau wie beim Schreiben eines node.js-Programms werden häufig Abhängigkeiten aus dem npm-Warehouse verwendet. In Vue beziehen sich Abhängigkeiten speziell auf reaktiv verarbeitete Daten. Wie später erwähnt wird, ist defineReactive eine der Schlüsselfunktionen der reaktiven Verarbeitung, die in vielen Artikeln zu Vue-Prinzipien erwähnt wird. Nachdem

Dep an alle reaktionsfähigen Daten gebunden ist, werden die reaktionsfähigen Daten zu einer Abhängigkeit (Substantiv). Bei der Einführung von Watcher wird unten erwähnt, dass reaktionsfähige Daten überwacht, berechnet oder in Vorlagen verwendet werden können (Verb).

subs

Dep Unter dem Objekt befindet sich ein Subs-Attribut, bei dem es sich um ein Array handelt. Es ist leicht zu erraten, dass es sich um die Abonnentenliste handelt. Abonnenten können Überwachungsfunktionen, berechnete Funktionen oder Ansichtsaktualisierungsfunktionen sein.

Watcher

Watcher ist der in Dep erwähnte Abonnent (nicht zu verwechseln mit dem Observer-Beobachter später).

Denn die Funktion von Watcher besteht darin, zeitnah auf Dep-Updates zu reagieren, genau wie der Abonnement-Push einiger Apps. Wenn Sie (Watcher) bestimmte Informationen (Dep) abonnieren, werden Sie daran erinnert, diese Informationen zu lesen aktualisiert.

deps

Ähnlich wie Dep das Subs-Attribut hat, hat das Watcher-Objekt auch das Deps-Attribut. Dies stellt eine Viele-zu-Viele-Beziehung zwischen Watcher und Dep dar. Der Grund für die gegenseitige Aufzeichnung besteht darin, dass die zugehörigen Objekte rechtzeitig aktualisiert werden können, wenn eine Partei gelöscht wird.

Watcher So generieren Sie

Die oben oft erwähnten Überwachungs-, Berechnungs- und Rendering-Vorlagen generieren einen Watcher, der im Vue-Quellcode prägnant und leicht verständlich ist:

  • mountComponent's vm._watcher = new Watcher(vm , updateComponent, noop);
  • initComputed’s watchers[key] = new Watcher(vm, getter || noop, noop, berechneteWatcherOptions)
  • $watcher’s var watcher = new Watcher(vm, expOrFn, cb, options);

Observer

Observer ist ein Beobachter, der für die rekursive Beobachtung (oder Verarbeitung) reaktiver Objekte (oder Arrays) verantwortlich ist. Im gedruckten Beispiel können Sie erkennen, dass die reaktiven Objekte einen __ob__ haben, der ein Beweis für das ist, was beobachtet wurde. Beobachter sind nicht so wichtig wie Dep und Watcher oben, nur ein wenig Verständnis reicht aus.

walk

Observer.prototype.walk ist die Kernmethode der rekursiven Verarbeitung bei der Initialisierung von Observer. Diese Methode wird jedoch zum Verarbeiten von Objekten verwendet, und es gibt auch Observer.prototype.observeArray zum Verarbeiten von Arrays.

Kernprozess

Wie lassen sich die oben genannten Konzepte entsprechend der Beziehung zwischen ihnen anpassen und eine reaktionsfähige Datenaktualisierung erreichen?

Legen Sie zunächst unser Ziel fest: Wenn die Daten aktualisiert werden, wird die Ansicht natürlich automatisch aktualisiert, um die neuesten Daten anzuzeigen.

Dies ist die oben erwähnte Beziehung zwischen Dep und Watcher. Die Daten sind Dep, und Watcher löst die Seitenrenderingfunktion aus (dies ist der wichtigste Watcher).

Aber es stellt sich eine neue Frage: Woher weiß Dep, dass ein Wächter von ihm abhängig ist?

Vue verwendet eine sehr interessante Methode:

  • Bevor Sie die Callback-Funktion des Watchers ausführen, notieren Sie sich zunächst den aktuellen Watcher (über Dep.target).

  • Reaktive Daten werden beim Ausführen der Callback-Funktion verwendet Die Getter-Funktion der Antwortdaten wird zwangsläufig aufgerufen

  • In der Getter-Funktion der Antwortdaten kann der aktuelle Watcher aufgezeichnet werden, und die Beziehung zwischen Dep und Watcher wird hergestellt. Danach werden die Antwortdaten aktualisiert , wird es zwangsläufig die Setter-Funktion sein, die die reaktiven Daten aufruft die defineReactive-Funktion. Es gibt viele Eingänge zu dieser Funktion. Lassen Sie uns zunächst über die wichtigere Beobachtungsfunktion sprechen.

  • In der Beobachtungsfunktion wird ein neues Observer-Objekt erstellt, in dem Observer.prototype.walk verwendet wird, um die Werte im Objekt einzeln und reaktionsschnell zu verarbeiten, und die Funktion defineReactive wird verwendet.
  • Da die Funktion defineReactive so wichtig und nicht lang ist, ist es bequemer, sie direkt hier zu veröffentlichen.

    function defineReactive(obj, key, val, customSetter, shallow) {
      var dep = new Dep()
      depsArray.push({ dep, obj, key })
      var property = Object.getOwnPropertyDescriptor(obj, key)
      if (property && property.configurable === false) {
        return
      }
    
      // cater for pre-defined getter/setters
      var getter = property && property.get
      var setter = property && property.set
    
      var childOb = !shallow && observe(val)
      Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
          var value = getter ? getter.call(obj) : val
          if (Dep.target) {
            dep.depend()
            if (childOb) {
              childOb.dep.depend()
              if (Array.isArray(value)) {
                dependArray(value)
              }
            }
          }
          return value
        },
        set: function reactiveSetter(newVal) {
          var value = getter ? getter.call(obj) : val
          // 后半部分诡异的条件是用于判断新旧值都是 NaN 的情况
          if (newVal === value || (newVal !== newVal && value !== value)) {
            return
          }
          // customSetter 用于提醒你设置的值可能存在问题
          if ('development' !== 'production' && customSetter) {
            customSetter()
          }
          if (setter) {
            setter.call(obj, newVal)
          } else {
            val = newVal
          }
          childOb = !shallow && observe(newVal)
          dep.notify()
        },
      })
    }
  • Zuallererst ist jeder responsive Wert eine „Abhängigkeit“, also nutzen wir im ersten Schritt die Fähigkeit der Schließung, um für jeden Wert eine Dep zu erstellen. (Mit Vue 3 sind keine Schließungen erforderlich)
  • Dann schauen Sie sich die drei Kernparameter an:

obj Das Objekt, bei dem der Wert aktuell reaktionsfähig verarbeitet werden muss

key Der Schlüssel des Werts

val Current Für den Wert von

    sind möglicherweise zuvor eigene Getter und Setter definiert. Bei der reaktionsfähigen Verarbeitung von Vue sollten daher zuerst die ursprünglichen Getter und Setter verarbeitet werden.
  • Wie oben im Kernprozess erwähnt, stellt die Getter-Funktion die Beziehung zwischen Dep und Watcher her und stützt sich dabei insbesondere auf dep.depend().

  • Im Folgenden werden verschiedene Methoden aufgeführt, wie Dep und Watcher sich gegenseitig anrufen können:
  • Dep.prototype.depend = function depend() {
      if (Dep.target) {
        Dep.target.addDep(this)
      }
    }
    Watcher.prototype.addDep = function addDep(dep) {
      var id = dep.id
      if (!this.newDepIds.has(id)) {
        this.newDepIds.add(id)
        this.newDeps.push(dep)
        if (!this.depIds.has(id)) {
          dep.addSub(this)
        }
      }
    }
    Dep.prototype.addSub = function addSub(sub) {
      this.subs.push(sub)
    }

    通过这几个函数,可以领略到了 Dep 和 Watcher 错综复杂的关系……不过看起来迂回,简单来说,其实做的就是上面说的互相添加到多对多列表。

    你可以在 Dep 的 subs 找到所有订阅同一个 Dep 的 Watcher,也可以在 Watcher 的 deps 找到所有该 Watcher 订阅的所有 Dep。

    但是里面还有一个隐藏问题,就是 Dep.target 怎么来呢?先放一放,后会作出解答。先接着看看 setter 函数,其中的关键是 dep.notify()。

    Dep.prototype.notify = function notify() {
      // stabilize the subscriber list first
      var subs = this.subs.slice()
      for (var i = 0, l = subs.length; i < l; i++) {
        subs[i].update()
      }
    }

    不难理解,就是 Dep 提醒他的订阅者列表(subs)里的所有人更新,所谓订阅者都是 Watcher,subs[i].update() 调用的也就是 Watcher.prototype.update。

    那么来看一下 Watcher 的 update 做了什么——

    Watcher.prototype.update = function update() {
      if (this.lazy) {
        this.dirty = true
      } else if (this.sync) {
        this.run()
      } else {
        queueWatcher(this)
      }
    }

    在这里我觉得有两个点比较值得展开,所以挖点坑

Das obige ist der detaillierte Inhalt vonWas ist das Responsivitätsprinzip von Vue?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen