前言
- 本文是vue|源码篇|1.0版本数据观测 依赖收集的续版,如果有vue数据驱动、依赖收集理解基础的同学可以直接上手,如无,建议阅读上篇文章
- 文章结构采用【指出阶段目标,然后以需解决问题为入口,以解决思路为手段】达到本文目标,若使诸君稍有启发,不枉此文心力^-^
目标
实现watch
- 属性改变,会触发watch中定义的函数执行
- watch多个写法的实现
实现computed
- 以computed中属性对应函数返回值为属性值
- computed缓存特性,即多次取同一属性,当其依赖属性未改变时不会重新计算
实现watch和computed
核心:一定要理解,页面渲染是取值操作,会触发数据属性的get
实现watch 很精妙 (精美)
核心思路:取值会触发属性的get,从而将当前的计算属性watcher存入当前监听的属性的dep中,并记录当前值;下一次再触发时,如果是计算属性Watcher(user:true),则将新老值传递给回调并执行
实现computed 更有趣(更难懂。。)
核心:默认不执行,当取值时会触发computed属性的get方法(需新定义),如果dirty为true(计算属性的标识是lazy)则执行exec方法求值;求值时会触发被依赖属性的get方法,从而将当前的计算属性watcher存入被依赖属性的dep中,
问题
-
computed与watch相比的差别是什么?都说computed有缓存,是指什么?怎么实现的
- 用户取值才执行
- 默认取老值,依赖值更改时才重新取新值
-
大家有没有注意到,如果被依赖属性没有在页面取值,也就是她的dep中并不会存入渲染watcher,那就会导致,其实页面并不会更新,怎么解决?
- 在计算属性的get中进行判断,如果Dep.target 不为空,即为渲染watcher,那就将这个watcher存入被依赖属性中即可
小结
-
watch其实就是预定义的this.$watch
-
computed 属性 是有节流效果的
-
这两者的实现都是基于依赖收集的,或者说是对watcher和dep的巧妙应用
多则惑少则得,如果只能记住一句话:watch的多个定义格式巧用很方便
。。。深度观测
obj:{
handler(newValue, oldValue) {
//do something
console.log(newValue,oldValue)
},
deep:true
}
。。。立即执行
obj:{
handler(newValue, oldValue) {
//do something
console.log(newValue,oldValue)
},
deep:true,
immediate: true
}
。。。。。观测对象中的某个属性
"obj.acount":{
handler(newValue, oldValue) {
//do something
console.log(newValue,oldValue)
},
deep:true,
immediate: true
}