一、侦听属性watch:
1、不支持缓存,当数据变化时,会直接触发对应的操作。
2、watch支持异步
3、监听函数接收两个参数,第一个新值,第二个旧值。
4、当一个属性发生变化时,需要执行对应的操作,一对多;
5、监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发对应的操作.
函数有两个参数: immediate:组件加载立即触发回调函数执行;
deep:深度监听,为了发现对象内部值的变化,复杂类型的数据使用,例如数组中的对象内容的改变,注意监听数组的变化不需要这么做。
注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
6、当需要在数据变化时执行异步或者开销较大的操作时,使用watch是最佳的。
截屏2021-07-01 上午10.35.17.png
二、计算属性computed:
1、支持缓存,只有依赖数据发生变化时,才会重新进行计算
2、不支持异步,当computed内有异步操作时无效,无法监听数据变化
3、computed属性值默认会走缓存,计算属性是基于他们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值。
4、如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一对一或者多对一,一般用computed。
6、如何实现缓存,其实就是使用dirty标志位来标识数据有没有更新,
在计算属性初始化时,会将computed对象中的每一个key创建一个watcher,当值发生变化的时候,会调用update方法将dirty置为true,当每次取值时会根据dirty来判断是重新计算还是直接读取值,如果dirty为true,调用evaluate函数重新计算,将dirty置为false;如果dirty为false,直接读取值.
Object.defineProperty(target, key, {
get() {
// 从刚刚说过的组件实例上拿到 computed watcher
const watcher = this._computedWatchers && this._computedWatchers[key]
if (watcher) {
// 条件成立说明值更新过,需要重新计算
if (watcher.dirty) {
// 这里会求值 调用 get
watcher.evaluate()
}
if (Dep.target) {
watcher.depend()
}
// 最后返回计算出来的值
return watcher.value
}
}
evaluate () {
// 调用 get 函数求值
this.value = this.get()
// 把 dirty 标记为 false
this.dirty = false
}
update () {
if (this.lazy) {
this.dirty = true
}
}
网友评论