Vue3 响应式系统的原理是什么?和 Vue2 有什么区别?
Vue3 响应式原理
Vue3 使用 Proxy 实现响应式,核心流程:
读取属性 → track(收集依赖)
修改属性 → trigger(触发更新)reactive 实现(简化版)
const targetMap = new WeakMap() // 存储依赖关系
let activeEffect = null
function track(target, key) {
if (!activeEffect) return
let depsMap = targetMap.get(target)
if (!depsMap) targetMap.set(target, (depsMap = new Map()))
let dep = depsMap.get(key)
if (!dep) depsMap.set(key, (dep = new Set()))
dep.add(activeEffect)
}
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const dep = depsMap.get(key)
if (dep) dep.forEach(effect => effect())
}
function reactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
track(target, key)
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
trigger(target, key)
return result
}
})
}effect 实现
function effect(fn) {
activeEffect = fn
fn() // 执行时触发 get → track
activeEffect = null
}
// 使用
const state = reactive({ count: 0 })
effect(() => {
console.log('count:', state.count) // 首次执行,track 收集依赖
})
state.count = 1 // trigger → 重新执行 effect → 输出 'count: 1'ref 实现
function ref(value) {
return {
get value() {
track(this, 'value')
return value
},
set value(newVal) {
value = newVal
trigger(this, 'value')
}
}
}Vue2 vs Vue3
| 特性 | Vue2 (Object.defineProperty) | Vue3 (Proxy) |
|---|---|---|
| 监听新增属性 | ❌ 需要 Vue.set |
✅ 自动 |
| 监听删除属性 | ❌ 需要 Vue.delete |
✅ 自动 |
| 监听数组索引 | ❌ 需要 hack | ✅ 自动 |
| 监听数组长度 | ❌ | ✅ |
| Map/Set 支持 | ❌ | ✅ |
| 深层监听 | 初始化时递归 | 懒代理(访问时才代理) |
| 性能 | 初始化慢 | 初始化快 |
| 兼容性 | IE9+ | 不支持 IE |
Vue2 的数组 hack
// Vue2 需要重写数组方法
const arrayMethods = Object.create(Array.prototype)
['push', 'pop', 'shift', 'unshift', 'splice'].forEach(method => {
arrayMethods[method] = function (...args) {
const result = Array.prototype[method].apply(this, args)
// 手动触发更新
notifyChange(this)
return result
}
})Vue3 深层响应式(懒代理)
// Vue3 只有在访问深层属性时才创建代理
const state = reactive({ user: { name: 'Tom' } })
// state.user 在首次访问时才被 reactive 包装
// 比 Vue2 初始化时递归遍历所有属性更高效Vue3 的优势
- Proxy 原生支持新增/删除属性
- 原生支持数组操作
- 支持 Map/Set/WeakMap
- 懒代理,性能更好
- 代码更简洁