记录:Vue computed实现deep监听踩坑
背景
在写 Vue 组件的时候,其中的 computed 里面依赖了一个对象,例如:
1 | new Vue({ |
以上述代码为例, dateRange computed 属性依赖了 date 这个对象,理想情况下, dateRange 会随着 date 对象内容的改变而改变。
然而,当单独改变 date.start 或 date.end 时,dateRange 却没有做出响应,见下面的示例:
原因分析
直接看 vue2 有关初始化 computed 部分的源码:
1 | const computedWatcherOptions = { lazy: true } |
可以看到,初始化的 computed 实际上就是个不带 deep 的 Watcher ,所以在收集依赖的时候, dateRange 只收集到了 date ,而没有收集到 date.start 和 date.end ,因此也就不会对这两个属性的单独变化做出响应。
解决
那要怎么在 computed 里实现类似 deep 的效果呢?实际上,使用 computed 的一般不会是什么特别复杂的属性,否则直接用 watch 就行了。
对于这类 computed ,有两种十分简单的方案:
- 改变对象时将整个对象一起改变,例如
this.date = {},而不是this.date.start = xxx - 在 computed 里将希望监听的属性都访问一遍,调用对象深层属性的 getter 。例如在上述示例中,在
dateRange中访问一遍this.date.start跟this.date.end即可。
可在示例中将注释去掉查看 computed 触发更新效果。