Vue 2 迁移 Vue 3(一):响应式原理之变
Vue 2 迁移 Vue 3(一):响应式原理之变
团队的老项目开始评估迁移,响应式系统是两代框架差异的根源,先把它搞透。
Vue 2:Object.defineProperty
核心是遍历 data 对象的每个属性,用 getter/setter 劫持读写:
function defineReactive(obj, key) {
let val = obj[key]
Object.defineProperty(obj, key, {
get() {
dep.depend() // 收集依赖:谁读了这个属性
return val
},
set(newVal) {
val = newVal
dep.notify() // 通知更新
},
})
}
天生有两个短板:
- 监听不到新增/删除属性——defineProperty 只能劫持初始化时已存在的 key,所以要
this.$set(obj, 'newKey', v)打补丁 - 数组下标和 length 监听不到——直接
arr[0] = x不更新,Vue 只能重写 push/splice 等 7 个变异方法绕过 - 深层对象要递归遍历到底,初始化开销大
Vue 3:Proxy
Proxy 代理整个对象,不关心具体有哪些 key:
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
track(target, key) // 收集依赖
const res = Reflect.get(target, key, receiver)
return typeof res === 'object' ? reactive(res) : res // 懒代理:访问到才递归
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
trigger(target, key) // 通知更新
return result
},
})
}
改进是质变:
- 新增属性、删除属性(delete)天然可拦截,$set 可以删了
- 数组下标、length、Map/Set 全部支持
- 只有被访问到的嵌套对象才代理,初始化快
注意 Proxy 代理的是对象,所以值类型才需要 ref(内部用 .value 的 getter/setter 包装)。
迁移注意点
- 原来靠 $set/$delete 修的代码可以简化,但要检查有没有"依赖不触发更新"的隐性逻辑
- 响应式判断:
Vue.observable→reactive;Vue.observable用法全部替换 - Proxy 无法 polyfill,IE11 彻底不支持(需要兼容 IE 的项目只能留在 Vue 2.7)
下一篇讲组件写法和逻辑复用的迁移。
看到这里了?如果这篇文章帮到过你
请我喝瓶可乐就好 🥤

评论0 条
还没有评论,来抢沙发~