Heim  >  Artikel  >  Web-Frontend  >  Was ist das Reaktionsfähigkeitsprinzip von Vue3?

Was ist das Reaktionsfähigkeitsprinzip von Vue3?

王林
王林nach vorne
2023-05-24 17:55:231242Durchsuche

Proxy

Die Kern-API von Proxy basiert auf dem reaktiven Prinzip von Vue3. Proxy kann zum Abfangen einiger Objektoperationen verwendet werden.

const obj = { a: 1 };
const p = new Proxy(obj, {
  get(target, property, receiver) {
    console.log("get");
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log("set");
    return Reflect.set(target, property, receiver);
  },
  has(target, prop) {
    console.log("has");
    return Reflect.has(target, prop);
  },
  deleteProperty(target, prop) {
    console.log("deleteProperty");
    return Reflect.deleteProperty(target, prop);
  },
});

p.a; // 输出 --> get
p.a = 2; // 输出 --> set
"a" in p; // 输出 --> has
delete p.a; // 输出 --> deleteProperty

Im obigen Beispiel verwenden wir Proxy, um den Eigenschaftszugriff, die Eigenschaftszuweisung, den In-Operator und die Löschvorgänge des Obj-Objekts zu vertreten und die Ausgabe von console.log durchzuführen.

Reflect

Reflect ist eine API, die in Verbindung mit Proxy verwendet wird. Wenn wir bestimmte Vorgänge kapern und diese Vorgänge zurückspiegeln müssen, müssen wir diese API widerspiegeln.

Da wir die Operationen des Objekts abgefangen haben, gehen die Funktionen dieser Operationen verloren. Wenn wir beispielsweise auf das Attribut p.a zugreifen, erhalten wir zu diesem Zeitpunkt keine Ergebnisse Wenn wir die Funktion vor der Abfangfunktion haben, müssen wir Reflect verwenden, um sie zurückzuspiegeln.

const obj = { a: 1 };
const p = new Proxy(obj, {
  get(target, property, receiver) {
    console.log("get");
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log("set");
    return Reflect.set(target, property, receiver);
  },
  has(target, prop) {
    console.log("has");
    return Reflect.has(target, prop);
  },
  deleteProperty(target, prop) {
    console.log("deleteProperty");
    return Reflect.deleteProperty(target, prop);
  },
});

Geben Sie ein Beispiel

Anhand dieses Beispiels beschreiben wir im folgenden Text das Prinzip der Vue3-Reaktionsfähigkeit.

<div id="app"></div>

<script>
  // 创建一个响应式对象
  const state = reactive({ counter: 1 });

  // 立即运行一个函数,当响应式对象的属性发生改变时重新执行。
  effect(() => {
    document.querySelector("#app").innerHTML = state.counter;
  });

  // 2s 后视图更新
  setTimeout(() => {
    state.counter += 1;
  }, 2000);
</script>

Wir haben reaktiv einen reaktionsfähigen Objektstatus erstellt und die Effektmethode aufgerufen, die eine Nebeneffektfunktion akzeptiert. Bei der Ausführung des Effekts wird sofort die Nebeneffektfunktion aufgerufen und state.counter zwei Sekunden lang zugewiesen Schließlich ist state.counter += 1. Zu diesem Zeitpunkt wird die Nebeneffektfunktion des Effekts erneut ausgeführt und die Seite wird zu 2. Der interne Ausführungsprozess ist ungefähr wie in der folgenden Abbildung dargestellt:

Was ist das Reaktionsfähigkeitsprinzip von Vue3?

    Call reactive() Gibt ein Proxy-Objekt zurück und entführt die Get- und Set-Operationen des Objekts. Wenn die effect()-Methode aufgerufen wird, wird auf die Eigenschaft state.counter zugegriffen, wodurch die Get-Operation des Proxys ausgelöst wird. Die
  • get-Methode ruft track() auf, um eine Abhängigkeitsbeziehung zwischen einem Objekt (Zustand), einem Attribut (Zähler) und einer Effekt-Nebeneffektfunktion herzustellen; die
  • set-Methode ruft trigger() auf; um Abhängigkeiten zu aktualisieren; durch Das Objekt (Zustand) und das Attribut (Zähler) finden Sie die entsprechende Nebenwirkungsfunktion und führen Sie sie dann erneut aus.
  • reactive
  • reactive gibt das folgende Proxy-Objekt zurück:

    const reactive = (target) => {
      return new Proxy(target, {
        get(target, key, receiver) {
          const res = Reflect.get(target, key, receiver);
    
          track(target, key); // 收集依赖
    
          if (isObject(res)) {
            // 如果当前获取的属性值是一个对象,则继续将为此对象创建 Proxy 代理
            return reactive(res);
          }
    
          return res;
        },
    
        set(target, key, value, receiver) {
          Reflect.set(target, key, value, receiver);
          trigger(target, key); // 依赖更新
        },
      });
    };
  • effect
let activeEffect;
function effect(fn) {
  const _effect = function reactiveEffect() {
    activeEffect = _effect;
    fn();
  };

  _effect();
}

Definieren Sie eine globale ActiveEffect-Variable, die auf die aktuell ausgeführte Effekt-Nebeneffekt-Funktion verweist und diese auf dem neuesten Stand hält. effect erstellt eine interne Nebeneffektfunktion für fn und führt sie dann sofort aus. Zu diesem Zeitpunkt wird die Get-Operation des Objekts ausgelöst und die Methode track() aufgerufen.

effect(() => {
  // effect 的立即执行会访问 state.counter,触发了对象的 get 操作。
  document.querySelector("#app").innerHTML = state.counter;
});

track

track erstellt eine Abhängigkeit eines Objekts (Zustand) => Attribut (Zähler) => Effekt

const targetMap = new WeakMap();
function track(target, key) {
  if (!activeEffect) {
    return;
  }

  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }

  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }

  if (!dep.has(activeEffect)) {
    dep.add(activeEffect);
  }
}

Nach Abschluss der Ausführung erhalten wir die folgende Datenstruktur:

[ // map 集合
  {
    key: {counter: 1} // state 对象,
    value: [ // map 集合
      {
        key: "counter",
        value: [ // set
          function reactiveEffect() {} // effect 副作用函数
        ],
      }
    ],
  },
];

Hinweis: Wann Wann Wenn wir den Effekt aufrufen, weisen wir die aktuelle Nebeneffektfunktion dem globalen aktiven Effekt zu, damit wir seine Abhängigkeiten zu diesem Zeitpunkt korrekt zuordnen können.

Trigger

Wenn wir state.counter einen Wert zuweisen, wird die Set-Operation des Proxy-Objekts ausgelöst und somit die Trigger-Methode aufgerufen

setTimeout(() => {
  // 给 counter 属性赋值会触发 set 操作
  state.counter += 1;
}, 2000);
function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;

  const effects = depsMap.get(key);
  effects && effects.forEach((effect) => effect());
}

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

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