聊聊Vue2/3的响应式系统的异同

288 阅读3分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

Vue3 响应式好在哪里?

实际上使用 proxy 代替 defineproperty 的方案从这两个API的角度来讲, 并没有什么显著的提升, 甚至 proxy 的性能要比 defineproperty 差.

但是在复杂对象的处理上, proxy的优势就很明显了. Vue2 中 defineproperty 所做的是对单个属性的劫持. 如果目标是一个复杂对象, 在项目初始化的时候, 不可避免的就需要预先对目标进行遍历, 使得全部数据被劫持. 而在Vue3中 proxy 是对对象本身进行劫持的. 而仅当我们访问了被劫持对象内的对象的时候, 这个内嵌对象才会被Vue劫持. 这就起到了一个懒加载的作用.

在Vue2中数组进行数据劫持, 还需要重写许多API, 并且 defineproperty 是不支持诸如map, set 等API的数据劫持的. 但是Vue3 天然规避了这个问题.

笔者上述提到的优化, 对于响应式的优化,都是很小的. 真正质的优化是一个minor版本, 也就是Vue3.2提出的. 一个社区大佬完成了这一壮举.细说 Vue.js 3.2 关于响应式部分的优化感兴趣的, 可以看看黄佬这篇文章.

Vue2/3 响应式哪里一样?

设计理念是一样的, 本质上, 诸如渲染工作, 计算属性, 实际都是通过一个 effect 来完成, Vue2中则是 watcher. 数据被读取了. 3就通过 track 方法追踪, 而2则是通过 depend 方法进行依赖收集. 数据被改变, 3通过 trigger 遍历执行 targetMap(目标地图)找到对应的effect数组 dep 然后遍历执行. 2通过 notify 通知watcher队列更新

原理图:

Vue2_3响应式原理图 (1).png

Vue2/3 响应式哪里不一样?

  1. 实现上虽然原理相同, 但是命名上, 设计上有了差别. Vue2中的 watcher类 变成了effect函数尽管 effect函数内部是实现了一个 ReactiveEffect类.

  2. 并且Vue3中取消了负责依赖收集, 派发更新Dep类. 相反的是使用了一个 Set类 代替Dep. 尽管在Vue3的响应式系统中 track 和 trigger 函数与Vue2的 depend 和 notify 做的是一样的事情. 但是据尤大的说来看. 明明的跟换是因为他们两个之间的作用逻辑变了

  3. 在Vue2中, Watcher实例更像是被数据的Dep实例收集了起来. 而在Vue3中已经不存在一个Dep类负责收集了, 取而代之的是 track函数意为追踪. 这就像一个被动与主动的区别

  4. Vue2对于依赖的收集是每个Dep各自独立的. 而在Vue3中会预先定义一个目标地图targetMap, 并且所有的dep都会存储到这个地图里.

当然以上论述的不过是Vue2/3版本响应式的异同. 但是在其他原理也是有很多值得我们学习的地方的, 比方说在Vue3中不再会劫持全部数据, 而是把这个权利交由给用户了.

感谢😘


如果觉得文章内容对你有帮助: