VUE的一个特点就是数据响应式;当我们改变一个数据时,页面中所有用到该数据的地方都会发生改变;那么在这个过程中VUE都做了什么工作呢
我们可以简单模拟一下vue的响应式的核心代码
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 |
//VUE初始化阶段initData()函数会将data数据代理到vm._data中 let vm_data = { name:'lele', age:18 }; //二.通过订阅者发布者模式,通知需要改变数据的节点数据 //发布者 (依赖搜集器) class Dep{ constructor(){ this.subs = []//订阅者列表 }; addSub(watcher){ this.subs.push(watcher) }; notify(){ this.subs.forEach(item=>{ item.update() }) } } //订阅者 class watcher{ constructor(name){ this.name = name; } update(){//在数据变化的时候会 console.log(this.name + '发生了update') } } const dep = new Dep();//在数据初始化的时候每一个data属性都是一个依赖收集器 //一.通过Object.defineProperty()里的set和get函数,知道哪些数据发生了改变 Object.keys(vm_data).forEach(key => {//劫持vm._data数据 let value = vm_data[key]; Object.defineProperty(vm_data,key,{ set(newvalue){//改变属性的时候执行 进行发布更新 console.log(`我设置了${key}属性`); value = newvalue; dep.notify();//改变属性的时候就通知所有相关依赖发生变化 }, get(){//获取属性的时候执行 进行依赖搜集 //在complime模板编译的时候会为每一条数据添加一个watcher对象 let w1 = new watcher('message1');//模拟编译的时候添加的watcher let w2 = new watcher('message2'); dep.addSub(w1);//模拟将每一个wahcher搜集到对应的依赖里 dep.addSub(w2); console.log(`我获取了${key}属性`) return value } }); }) console.log(vm_data.name);//我获取了age属性 lele console.log(vm_data.age = 20);//我设置了age属性 20 |
vue2响应原理的缺点
VUE3响应原理:vue3改用了proxy代理方式实现数据响应;后续再研究