Vue2响应式原理
-
通过Object.defineProperty的方式实现对象属性的监听
// 保存当前需要收集的响应式函数 let activeReactiveFn = null; // 封装依赖收集类 class Depend { constructor() { // 使用Set防止函数重复添加 this.reactiveFns = new Set(); } depend() { if (activeReactiveFn) { this.reactiveFns.add(activeReactiveFn); } } notify() { this.reactiveFns.forEach((fn) => fn()); } } // 封装响应式函数 function watchFn(fn) { activeReactiveFn = fn; fn(); activeReactiveFn = null; } // 封装获取depend的函数 const targetMap = new WeakMap(); function getDepend(target, key) { // 根据target对象获取map let map = targetMap.get(target); if (!map) { map = new Map(); targetMap.set(target, map); } // 根据key获取depend对象 let depend = map.get(key); if (!depend) { depend = new Depend(); map.set(key, depend); } return depend; } // 监听对象的属性变量:proxy(vue3)/Object.defineProperty(vue2) function reactive(obj) { Object.keys(obj).forEach(key => { let value = obj[key] Object.defineProperty(obj, key, { get() { const depend = getDepend(obj, key) depend.depend() return value }, set(newValue) { value = newValue const depend = getDepend(obj, key) depend.notify() } }) }) return obj } // 将对象变为响应式,一个属性对应一个depend对象 const objProxy = reactive({ name: "zzy", // age: 22, }); const infoProxy = reactive({ address: "广州市", }); watchFn(() => { console.log(objProxy.name); }); watchFn(() => { console.log(infoProxy.address); }); objProxy.name = 'lll' infoProxy.address = "北京市";
Vue3响应式原理
-
通过Proxy的方式来监听数据的变化以及收集相关依赖
// 保存当前需要收集的响应式函数 let activeReactiveFn = null; // 封装依赖收集类 class Depend { constructor() { // 使用Set防止函数重复添加 this.reactiveFns = new Set(); } depend() { if (activeReactiveFn) { this.reactiveFns.add(activeReactiveFn); } } notify() { this.reactiveFns.forEach((fn) => fn()); } } // 封装响应式函数 function watchFn(fn) { activeReactiveFn = fn; fn(); activeReactiveFn = null; } // 封装获取depend的函数 const targetMap = new WeakMap(); function getDepend(target, key) { // 根据target对象获取map let map = targetMap.get(target); if (!map) { map = new Map(); targetMap.set(target, map); } // 根据key获取depend对象 let depend = map.get(key); if (!depend) { depend = new Depend(); map.set(key, depend); } return depend; } // 监听对象的属性变量:proxy(vue3)/Object.defineProperty(vue2) function reactive(obj) { return new Proxy(obj, { get(target, key, receiver) { console.log("get被访问", key, target); // 根据target和depend获取对应的depend const depend = getDepend(target, key); // 给depend对象中添加响应函数 depend.depend(); return Reflect.get(target, key, receiver); }, set(target, key, newValue, receiver) { console.log("set被访问", key, target, newValue); Reflect.set(target, key, newValue, receiver); const depend = getDepend(target, key); depend.notify(); }, }); } // 将对象变为响应式,一个属性对应一个depend对象 const objProxy = reactive({ name: "zzy", // age: 22, }); const infoProxy = reactive({ address: "广州市", }); watchFn(() => { console.log(objProxy.name); }); watchFn(() => { console.log(infoProxy.address); }); objProxy.name = 'lll' infoProxy.address = "北京市";