我们先来观察一下这段代码

你觉得当点击+号时,视图会如何更新?我给三个选项吧:

选项A:count1更新,count2不变

选项B:count1更新,count2改变但视图不更新

选项C:count1更新,count2改变且视图更新

我相信很大一部分人会选择A或者B,但当你亲自调试时发现,自己的直觉错误了。


我们先来回顾一下什么是shallowReactive,查阅一下官方文档,是这样描述的:

和 reactive() 不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。

对照上面代码来理解,nestedObj这个嵌套的对象,不再具备响应式,但为什么视图却更新了呢?

这里我提示一下,add这个方法的effect是什么?显然是Vue内部追踪到了test.count1的依赖,然后count1是第一层具备响应式的数据,Vue自然会触发更新。但是我们不要忽略一个点,此时count2其实数据发生改变了,而Vue的diff此时并不关心到底谁是reactive响应式对象,换言之,这次effect是数据驱动了视图发生了变化,而test.count1就是带动count2产生视图变化的“罪魁祸首”。

我们平时不能机械地将shallowReactive理解为一个不具备响应式的死数据,对于Vue来说,只是对于深层次的这些对象不再进行及时的追踪,但不代表不能手动更新或者由于副作用的影响而造成视图的变化。

diff是一个高明的算法,保证了视图更新的效率,且不至于消耗更多额外资源。