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

Vue计算源码分析

时间:2023-03-31 16:45:57 vue.js

1.每个计算属性都会生成一个对应的观察者(Watcher实例),观察者有一个values属性和一个get方法。在get方法中会调用计算属性的getter函数,将返回值赋值给value。最初将dirty和lazy的值设置为true。如果lazy为true,则get方法不会立即执行(惰性执行),而是在读取计算值时执行。functioninitComputed(vm,computed){varwatchers=vm._computedWatchers=Object.create(null);//存储计算的观察者varisSSR=isServerRendering();for(varkeyincomputed){varuserDef=computed[key];vargetter=typeofuserDef==='函数'?userDef:userDef.get;...watchers[key]=newWatcher(//生成一个watcher(Watcher实例)vm,getter||noop,//getternoop会在observer的get方法中执行,computedWatcherOptions//{lazy:true}会延迟执行,get方法暂时不会执行,会在读取到计算出的属性值时执行);...defineComputed(vm,key,userDef);……}}2。给组件实例添加计算属性,通过get、set、重定义getter函数获取或设置属性值,functiondefineComputed(target,key,userDef){varshouldCache=!isServerRendering();...sharedPropertyDefinition.get=shouldCache//重新定义getter函数?createComputedGetter(key):createGetterInvoker(userDef);...Object.defineProperty(target,key,sharedPropertyDefinition);//将计算属性添加到组件实例}//重新定义getter函数functioncreateComputedGetter(key){返回函数computedGetter(){varwatcher=this._computedWatchers&&this._computedWatchers[key];if(watcher){if(watcher.dirty){//true,惰性执行watcher.evaluate();//执行完watcher方法后,设置dirty为false}if(Dep.target){watcher.depend();}返回watcher.value;//返回watcher的值}};}3.页面初始渲染时,读取computed属性的值,触发重新定义的getter函数。由于观察者的脏值是true,所以会调用get方法执行原来的getter函数。data(响应式)数据会在getter函数中读取,数据读取时会触发data的getter方法,并将计算属性对应的observer添加到data的dependencycollector中(用于通知数据更改时更新)。观察者的get方法执行完后,更新观察者的值,并将dirty设置为false,表示值已经更新,然后执行观察者的depend方法,设置上层观察者(观察者包含页面updated方法,读取computed属性值)在getter函数中也加入了数据的依赖收集器(getter中数据的依赖收集器包含了computed对应的观察者,包含了页面更新方法(调用计算属性)观察者),最后返回计算观察者的值。4、当计算属性getter函数所依赖的数据值发生变化时,会按照之前收集到的观察者顺序调用观察者的update方法,先调用计算观察者的更新方法。由于lazy为true,所以会设置observer的dirty值为true,也就是说计算属性getter函数所依赖的数据值发生变化,但不会调用observer的get方法更新该值。然后调用包含页面更新方法的观察者的更新方法。当更新页面时,它会读取计算属性的值并触发重新定义的getter函数。此时由于computed属性的observer为dirty为true,调用observer的get方法,更新value值,返回完成页面渲染。5、脏值初始为true,即第一次读取计算属性值时,根据setter计算属性值并保存在观察者值上,然后将脏值设置为false。后面读取computed属性的值时,dirty值为false,不会调用setter重新计算值,而是直接返回observer的值,即上次计算的值。只有当计算属性setter函数所依赖的数据发生变化时,dirty才被设置为true,即下次读取计算属性的值时调用setter重新计算。也就是说,当计算属性所依赖的数据没有变化时,不会调用setter函数重新计算值,而是读取上次计算的值。