Proxy의 핵심 API는 Vue3의 반응 원리에 의존합니다. Proxy는 일부 객체 작업을 가로채는 데 사용될 수 있습니다.
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 개체의 속성 액세스, 속성 할당, 연산자 및 삭제 작업을 프록시하고 console.log 출력을 수행합니다.
Reflect는 특정 작업을 하이재킹할 때 이러한 작업을 다시 반영해야 하는 경우 프록시와 함께 사용되는 API입니다.
객체의 작업을 가로채기 때문에 이러한 작업의 기능은 손실됩니다. 예를 들어 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>
반응형 객체 상태를 생성하기 위해 반응형을 사용하고 부작용 함수를 허용하는 효과 메서드를 호출했습니다. 효과가 실행되면 즉시 부작용 함수가 호출되고 2초 동안 #app.innerHTML에 state.counter가 할당됩니다. 마지막으로 state.counter += 1. 이때 Effect의 Side Effect 기능이 다시 실행되어 페이지가 2가 됩니다. 내부 실행 과정은 대략 아래 그림과 같습니다.
reactive는 다음 프록시 객체를 반환합니다.
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); } }
실행이 완료되면 다음과 같은 데이터 구조를 얻게 됩니다.
[ // map 集合 { key: {counter: 1} // state 对象, value: [ // map 集合 { key: "counter", value: [ // set function reactiveEffect() {} // effect 副作用函数 ], } ], }, ];
trigger
state.counter에 값을 할당하면 프록시 객체의 설정 작업이 트리거되어 트리거 메서드가 호출됩니다.
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 중국어 웹사이트의 기타 관련 기사를 참조하세요!