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 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); }, });
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:
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); // 依赖更新 }, }); };
let activeEffect; function effect(fn) { const _effect = function reactiveEffect() { activeEffect = _effect; fn(); }; _effect(); }
effect(() => { // effect 的立即执行会访问 state.counter,触发了对象的 get 操作。 document.querySelector("#app").innerHTML = state.counter; });
track
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 副作用函数 ], } ], }, ];
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!