当前位置: 首页 > Web前端 > vue.js

vue2.x响应式原理

时间:2023-03-31 15:57:00 vue.js

vue3.0发布,回顾一波2.x原理vue2.x响应式原理主要做了以下几件事:数据劫持,集合依赖,分发更新数据劫持:newVue遍历数据时对象,使用Object.defineProperty为所有属性添加getter和setter依赖的集合:render的过程会触发数据的getter,并在getter的时候收集当前的watcher对象并分发更新:当setter时,遍历这个数据的依赖对象(watcher对象),更新数据。通过Object.defineProperty劫持对象属性,使数据成为可观察的classVue{constructor(options){observer(options.data);}observer(value){if(!value||(typeofvalue!=='object')){返回;}//遍历数据对象,逐一添加gettersetterObject.keys(value).forEach(key=>defineReactive(value,key,value[key]));}defineReactive(obj,key,val){constdep=newDep();//Dep是一个依赖集合类Object.defineProperty(obj,key,{enumerable:true,//propertyEnumerableconfigurable:true//属性可以被修改或删除get(){dep.addSub(Dep.target);//依赖集合returnval;},set(newVal){if(newVal===val)return;dep.notify(newVal);//Dispatchupdate}})}}可以看到主要是这个defineReactive函数,它使用了Object.defineProperty来实现数据劫持dependencycollection&dispatchupdate。那么Vue如何知道数据何时发生变化呢?我应该通知谁?它使用订阅者Dep,用于存储我们的观察者对象。当数据发生变化时,通知观察者,观察者通过调用自己的更新方法完成更新classDep{constructor(){this.newDeps=[]//用于存储我们的依赖对象(即观察者)}addDep(watcher){this.newDeps.push(watcher)//添加一个新的观察者到队列对象}update(){this.newDeps.forEach((sub)=>{sub.update();//遍历watcher进行更新})}}classWatcher{constructor(){Dep.target=this//newWatcher时,将observer存放在Dep中。target}update(){console.log("视图更新了~");//更新视图}}新建一个Watcher对象,此时会指向Dep.target,触发render进程中的getter,并将Dep.target添加到依赖队列。这样就完成了依赖项的收集。当数据发生变化时,通知取决于更新操作。以上代码是对2.x版本响应式原理的代码模拟。在Vue中,这些类都是单独的文件和源码地址。