框架原理精校教程
Vue 响应式原理
从依赖收集和派发更新出发,理解 Vue 2 与 Vue 3 响应式实现的关键差异。
vue实现响应式的原理
- 响应式的原理实际上是采用通过消息订阅发布模式来达到自动维护数据更新的目的
具体的过程:
- 定义响应式数据时,创建一个publisher实例,这个实例会创建一个记录依赖的数组,以及获取和修改数据的钩子函数
- 一旦(被)获取数据时(getter被调用),上述的publisher实例就会把获取数据的subscriber加入到依赖表中
- 一旦数据发生改变(setter被调用),publisher实例就会遍历依赖中的所有subscriber,调用其更新的方法,实现数据更新

- vue2使用Object.defineproperty方法去实现数据劫持,实际上是重写了对象属性的getter和setter方法,这个方法有一些不足,
- 在某些特定情况下会导致响应式丢失,如不改变原数组的数组操作,修改长度,操作下标等,给对象添加新属性,删除属性等,需要通过额外的操作来获得响应性 $set $delete (vue内部没有重写的数组方法,都会丢失响应式)
- 初始化时需要遍历对象的所有属性来添加setter和getter,性能比vue3低一点
- vue3使用的proxy来实现数据代理,相对于defineproperty,proxy可以直接监听对象的所有操作
vue2和 vue3对比,有哪些不同?
- Vue3新增了组合式函数(composition Api ),它可以带来2个方面的好处:
- 代码内聚性性更强,独立的操作,数据和方法可以单独抽离出来,方便代码维护
- 增强代码的复用,相同逻辑的代码单独抽离,只需要编写一次,就可以复用
对比mixin,hooks的数据来源更加清晰,也不会造成命名冲突
- 一些api优化,如去掉filter(建议使用computed实现,或者全局属性实现),$listener(合并到$attrs中)
- vue内部实现了tree shaking,减少了代码体积,如nextTick,在打包工具配置tree shaking的情况下,如果代码中没有使用,则不会被打包进去
- v-model使用改变,vue2默认使用的是value和@input来实现双向绑定值和更新值,vue3使用的是
- V-for v-if 优先级的改变 v3中v-if优先级更高
- key的改变,v3可以(也应该)绑定在template标签上,且v-if-else等分支不需要key,会自动生成。v2是在子组件上,
- v-bind的优先级改变,v3中,先写的属性会被后面的覆盖,而v2中atrrs会永远比v-bind绑定的优先级高,v-bind无法覆盖attrs
- v3中,.native修饰词移除,不包含在emits
- diff算法实现不同
v2中的diff算法使用双端队列实现,双指针,时间复杂度为On
v3中使用的时间复杂度是nlogn,但是v3减少了dom的移动的操作,所以性能更高(dom操作的开销更大)