computed的computed属性有缓存机制,只有当它依赖的响应式数据发生变化时,才会清空缓存,重新计算重新计算的结果。缓存机制的本质是由一个dirty属性控制的,只有dirty为真。结果将被重新计算以替换缓存。dirty只有在其响应式数据传输发生变化时才会设置为true,重新计算后会再次设置为false。在_computedWatchers中,传递给lazy的参数为true。如果计算属性与props中定义的数据或名称不冲突,则执行defineComputed方法。constcomputedWatcherOptions={lazy:true}functioninitComputed(vm:Component,computed:Object){constwatchers=vm._computedWatchers=Object.create(null)for(constkeyincomputed){constuserDef=computed[key]/*计算属性可以是函数,也可以是设置了get和set的对象。*/让getter=typeofuserDef==='函数'?userDef:userDef.get/*为计算属性创建一个内部监视器Watcher,保存在vm实例的_computedWatchers中。这里的computedWatcherOptions参数传递了一个lazy为true,将使watch实例的dirty变为true*/watchers[key]=newWatcher(vm,getter,noop,computedWatcherOptions)/*组件定义的计算属性已经被在现有组件的原型上定义,因此不会重复定义*/if(!(keyinvm)){/*definecomputedproperty*/defineComputed(vm,key,userDef)}elseif(process.env...Object.defineProperty再次进行包装,使用时触发get。get函数会对computedWatcher实例的脏值进行拦截判断。当它为真时,它会触发观察者类的评估函数。该函数用于获取值,最后关闭dirty。如果dirty为false,则直接返回第一次获取到的值,第二次获取到的值。exportfunctiondefineComputed(target:any,key:string,userDef:Object|Function){if(typeofuserDef==='function'){/*创建计算属性getter*/sharedPropertyDefinition.get=createComputedGetter(key)/*WhenuserDef是一个函数,不需要setter,所以这里设置为一个空函数。因为计算属性默认是一个函数,所以只设置了getter。当需要设置setter时,将计算属性设置为一个对象。参考:https://cn.vuejs.org/v2/guide/computed.html#Computation-setter*/sharedPropertyDefinition.set=noop}else{/*如果get不存在,会直接给空函数,如果存在,检查是否存在一个Cache缓存,如果没有赋值get,使用createComputedGetter创建*/sharedPropertyDefinition.get=userDef.get?userDef.cache!==false?createComputedGetter(key):userDef.get:noop/*如果有set方法则直接使用,否则赋空函数*??/sharedPropertyDefinition.set=userDef.set?userDef.set:noop}/*definePropertygetter和setter*/Object.defineProperty(target,key,sharedPropertyDefinition)}/*为计算属性创建一个getter*/functioncreateComputedGetter(key){returnfunctioncomputedGetter(){constwatcher=this._computedWatchers&&this._computedWatchers[key]if(watcher){/*dirty会在计算属性中的依赖发生变化时变为true,获取时重新计算计算属性的输出值*/if(watcher.dirty){watcher.evaluate()}/*依赖集合*/if(Dep.target){watcher.depend()}returnwatcher.value}}}/*Watcher*/evaluate(){this.value=this.get()this.dirty=false}中的evaluate函数,所以computed具有缓存的特性,只有当依赖的数据发生变化时,才会触发Object中的notify。definePropertyset方法通知所有观察者,并通知调用update。如果lazy在update中为true,dirty将被设置为true。一旦dirty为真,在获取Object.defineProperty(obj,key,{enumerable:true,configurable:true,get:functionreactiveGetter(){/*省略*/},set:functionreactiveSetter(newVal){/*省略*//*dep对象通知所有观察者*/dep.notify()}})/*dep/notify*/notify(){constsubs=this.潜艇。slice()for(leti=0,l=subs.length;i
