ホームページ > 記事 > ウェブフロントエンド > Vue3 の応答原理とは何ですか
プロキシのコア API は、Vue3 の応答原理に依存しています。プロキシは、一部のオブジェクト操作をインターセプトするために使用できます。
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
上記の例に示すように、Proxy を使用して、Obj オブジェクトのプロパティ アクセス、プロパティの割り当て、in 演算子、および削除操作をプロキシし、console.log 出力を実行します。
Reflect は Proxy と組み合わせて使用される API です。特定の操作をハイジャックしたときに、これらの操作を反映させる必要がある場合は、この API を Reflect する必要があります。
オブジェクトの操作をインターセプトしたため、これらの操作の機能は失われます。たとえば、属性 p.a にアクセスすると、a 属性の値が取得されるはずですが、この時点では結果は得られません。インターセプト前に関数を使用したい場合は、Reflect を使用して反射する必要があります。
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); }, });
この例を使用して、次のテキスト全体で Vue3 の応答性の原理を説明します。
<div id="app"></div> <script> // 创建一个响应式对象 const state = reactive({ counter: 1 }); // 立即运行一个函数,当响应式对象的属性发生改变时重新执行。 effect(() => { document.querySelector("#app").innerHTML = state.counter; }); // 2s 后视图更新 setTimeout(() => { state.counter += 1; }, 2000); </script>
reactive を使用してリアクティブ オブジェクトの状態を作成し、副作用関数を受け入れるエフェクト メソッドを呼び出しました。エフェクトを実行すると、すぐに副作用関数が呼び出され、state.counter が #app.innerHTML に割り当てられます。 ; 2 秒後、state.counter = 1. このとき、effect の副作用関数が再実行され、ページは 2 になります。以下の図:
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(); }
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); } }
実行が完了すると、A が得られますデータ構造は次のとおりです。
[ // map 集合 { key: {counter: 1} // state 对象, value: [ // map 集合 { key: "counter", value: [ // set function reactiveEffect() {} // effect 副作用函数 ], } ], }, ];
注:effect を呼び出すと、現在の副作用関数がグローバル activeEffect に割り当てられるため、この時点でその依存関係を正しく関連付けることができます。
trigger
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()); }が呼び出されます。
以上がVue3 の応答原理とは何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。