Vue3 响应式原理 Vue 3
约 631 字大约 2 分钟
2025-03-14
Vue 3 的响应式系统通过 Proxy 和 Reflect 实现,相较于 Vue 2 的 Object.defineProperty
,解决了无法检测新增/删除属性等限制。以下是其核心原理的逐步解析:
一、响应式对象创建(reactive
函数)
- 使用
Proxy
代理目标对象,拦截其操作(如get
、set
、deleteProperty
等)。 - 通过
Reflect
方法执行默认行为(如Reflect.get
),确保this
指向和继承关系正确。
function reactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver);
track(target, key); // 依赖收集
return isObject(res) ? reactive(res) : res; // 递归代理嵌套对象
},
set(target, key, value, receiver) {
const res = Reflect.set(target, key, value, receiver);
trigger(target, key); // 触发更新
return res;
},
// 其他拦截操作(如 deleteProperty)
});
}
二、依赖收集(track
)与触发更新(trigger
)
依赖存储结构:使用
WeakMap
嵌套Map
和Set
存储对象属性与副作用的关系。WeakMap<Target, Map<Key, Set<Effect>>>
track
函数:在属性被访问时,将当前运行的副作用(activeEffect
)存入对应集合。trigger
函数:在属性修改时,取出所有关联的副作用并执行。
let activeEffect;
const targetMap = new WeakMap();
function track(target, key) {
if (!activeEffect) return;
let depsMap = targetMap.get(target);
if (!depsMap) targetMap.set(target, (depsMap = new Map()));
let deps = depsMap.get(key);
if (!deps) depsMap.set(key, (deps = new Set()));
deps.add(activeEffect);
}
function trigger(target, key) {
const depsMap = targetMap.get(target);
if (!depsMap) return;
const effects = depsMap.get(key);
effects && effects.forEach((effect) => effect());
}
三、副作用管理(effect
函数)
- 副作用函数(如组件渲染、
watch
回调)被包裹在effect
中执行。 - 执行时,将当前副作用标记为
activeEffect
,触发依赖收集。
function effect(fn) {
const wrapper = () => {
activeEffect = wrapper;
fn();
activeEffect = null;
};
wrapper();
}
四、处理嵌套对象与数组
- 嵌套对象:在
get
拦截中递归调用reactive
,确保深层对象也是响应式的。 - 数组方法:Proxy 能拦截
push
、pop
等方法,自动处理length
变更触发的更新。
五、Ref 与响应式基础类型
对基础类型(如
number
)使用ref
,通过.value
访问,内部用对象包裹并代理。ref
的实现类似:function ref(value) { return reactive({ value }); }
六、关键优势
- 全面拦截:Proxy 支持监听属性新增、删除、数组索引变化等。
- 性能优化:惰性收集依赖,避免递归遍历对象。
- 自动解包:嵌套对象和数组无需手动处理。
七、总结
Vue 3 的响应式系统通过 Proxy 代理 + 依赖收集/触发 + 副作用管理 实现,解决了 Vue 2 的局限性,同时提升了灵活性和性能。
更新日志
2025/8/24 08:17
查看所有更新日志
e7112
-1于