深入理解Vue计算计算属性原理

  

计算计算属性是Vue中常用的一个功能,但你理解它是怎么工作的吗?

  

拿官网简单的例子来看一下:

        & lt; div id=袄印北?   & lt; p>原始消息:“{{消息}}”& lt;/p>   & lt; p>计算了消息:“{{reversedMessage}}”& lt;/p>   & lt;/div>   之前            var vm=new Vue ({   埃尔:“#例子”,   数据:{   消息:“你好”   },   计算:{//计算getter   reversedMessage:函数(){//这个点到vm实例   返回this.message.split (”) .reverse . join () ()   }   }   })   之前      


  

  

Vue里的计算属性非常频繁的被使用的到,但并不是很清楚它的实现原理,比如:计算属性如何与属性建立依赖关系?属性发生变化又如何通知到计算属性重新计算吗?

  

关于如何建立依赖关系,我的第一个想到的就是语法解析,但这样太浪费性能,因此排除,第二个想到的就是利用JavaScript单线程的原理和Vue的Getter设计,通过一个简单的发布订阅,就可以在一次计算属性求值的过程中收集到相关依赖。

  

因此接下来的任务就是Vue源从码一步步分析计算的实现原理。

  

  

分析依赖收集实现原理,分析动态计算实现原理。

  


  

  

数据属性初始化getter setter:

     //src/观察者/index.js//这里开始转换数据的getter setter,原始值已存入到__ob__属性中   Object.defineProperty (obj,钥匙,{   可列举的:真的,   可配置:没错,   得到:reactiveGetter函数(){   常量值=https://www.yisu.com/zixun/getter ?getter.call (obj):瓦尔//判断是否处于依赖收集状态   如果(Dep.target) {//建立依赖关系   dep.depend ()   …   }   返回值   },   设置:函数reactiveSetter (newVal) {   …//依赖发生变化,通知到计算属性重新计算   dep.notify ()   }   })      之前      

     //src/核心//state.js实例//初始化计算属性   函数initComputed (vm:组件计算:对象){   …//遍历计算计算属性   (const关键计算){   …//创建观察家实例//创建内部计算属性的观察家。   观察者(例子)=新观察家(vm, getter | |等待,等待,computedWatcherOptions)//创建属性vm。reversedMessage,并将提供的函数将用作属性vm。reversedMessage的getter,//最终计算与数据会一起混合到vm下,所以当计算与数据存在重名属性时会抛出警告   defineComputed (vm、关键,userDef)   …   }   }      导出功能defineComputed(目标:任何关键:字符串,userDef:对象|函数){   …//创建预备方法   sharedPropertyDefinition。得到=createComputedGetter(键)   sharedPropertyDefinition。设置=等待   …//创建属性vm。reversedMessage,并初始化getter setter   Object.defineProperty(目标、关键、sharedPropertyDefinition)   }      函数createComputedGetter(关键){   返回函数computedGetter () {   const观察家=computedWatchers,,this._computedWatchers(例子)   如果(观察者){   如果(watcher.dirty) {//观察者暴露评估方法用于取值操作   watcher.evaluate ()   }//同第1步,判断是否处于依赖收集状态   如果(Dep.target) {   watcher.depend ()   }   返回watcher.value   }   }   }      之前      

无论是属性还是计算属性,都会生成一个对应的观察家实例。

     //src/核心/观察者/watcher.js//当通过vm。reversedMessage获取计算属性时,就会进到这个getter方法   get () {//这指的是观察者实例//将当前观察家实例暂存到Dep.target,这就表示开启了依赖收集任务   pushTarget(这)   我们的价值   const vm=this.vm   尝试{//在执行vm。reversedMessage的函调函数时,会触发属性(步骤1)和计算属性(步骤2)的getter//在这个执行过程中,就可以收集到vm。reversedMessage的依赖了   值=https://www.yisu.com/zixun/this.getter.call(虚拟机,虚拟机)   }捕捉(e) {   如果(this.user) {   handleError (e, vm的getter观察家“$ {this.expression} ")   其他}{   把e   }   最后}{   如果(this.deep) {   遍历(值)   }//结束依赖收集任务   popTarget ()   this.cleanupDeps ()   }   返回值   }      之前      

上面多出提到了dep.depend, dep.notify, Dep.target,那么Dep究竟是什么呢?

深入理解Vue计算计算属性原理