vue2响应式--深度监听模拟
上篇优化了重复的监听,但当data数据为下图一个嵌套数据时,深层嵌套的属性没有响应效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import { observe } from "./observer" ; import { Watcher } from "./watcher" ; const data = { test: "aa" , test1: "cc" , test2: { dd: "aa" , }, }; const recursion = () => { console.log(data.test2.dd); }; observe(data); new Watcher(recursion); data.test2.dd = "as" ; // 直接修改响应式没有触发 data.test2 = { dd: "ss" , }; //整体赋值才有响应效果效果 |
我们发现整体赋值才可以有效果,我们就可以在数据劫持时判断当前的key值是否为对象类型,如果为对象类型就调用observe方法,对key值进行响应式。observer.js具体实现如下:
shallow属性设置数据是否需要深度监听,这样就可以深度监听了,但当我们重新对一个对象赋值后,再修改属性又没有响应效果,所以再set 方法里也添加一个深度监听方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import Dep from "./dep" ; const NO_INIITIAL_VALUE = {}; function defineReactive(obj, key, val, shallow) { // 获取当前属性有没有自定义方法; let property = Object.getOwnPropertyDescriptor(obj, key); // 判断当前属性有没有自定义get set 方法 let getter = property && property.get; let setter = property && property.set; // 没有val值,去obj里面的 if ( (!getter || setter) && (val === NO_INIITIAL_VALUE || arguments.length == 2) ) { val = obj[key]; } const dep = new Dep(); // 如果val值为对象类型,则深度监听 let childOb = !shallow && observe(val, false ); Object.defineProperty(obj, key, { enumerable: true , configurable: true , get: function () { //添加依赖函数 if (Dep.target) { // dep.addSub(Dep.target); dep.depend(); } //如果有自定义方法则调用 let value = getter ? getter.call(obj) : val; return value; }, set: function (newVal) { if (setter) { setter.call(obj, newVal); } else { val = newVal; } // 如果对一个对象整体赋值后,再修改对象属性也没有响应效果,在set也监听下 childOb = !shallow && observe(newVal, false ); //执行依赖当前属性的依赖函数 dep.notify(); }, }); } export class Observer { constructor(data, shallow = false ) { // shallow 属性判断是否需要深度监听 this .observer(data, shallow); } observer(data, shallow) { let keys = Object.keys(data); for ( let key of keys) { defineReactive(data, key, NO_INIITIAL_VALUE, shallow); } } } function observe(data, shallow = false ) { if ( typeof data == "object" ) { return new Observer(...arguments); } else { return false ; } } export { observe }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import { observe } from "./observer" ; import { Watcher } from "./watcher" ; const data = { test: "aa" , test1: "cc" , test2: { dd: "aa" , }, }; const recursion = () => { console.log(data.test2.dd); }; observe(data); // 深度响应 new Watcher(recursion); data.test2.dd = "as" ; data.test2 = { dd: "ss" , }; data.test2.dd = "111" ; // 在set里添加深度监听 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具