proxy实现vue
使用 Proxy 实现 Vue 响应式系统
Vue 3 的响应式系统基于 JavaScript 的 Proxy API,通过代理对象实现对属性的拦截和依赖追踪。以下是实现的核心逻辑:

创建响应式对象
function reactive(target) {
const handler = {
get(target, key, receiver) {
track(target, key); // 依赖收集
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
const oldValue = target[key];
const result = Reflect.set(target, key, value, receiver);
if (oldValue !== value) {
trigger(target, key); // 触发更新
}
return result;
}
};
return new Proxy(target, handler);
}
依赖收集与触发
const targetMap = new WeakMap(); // 存储依赖关系
function track(target, key) {
if (activeEffect) {
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 effects = depsMap.get(key);
effects && effects.forEach(effect => effect());
}
实现计算属性
let activeEffect;
function effect(fn) {
activeEffect = fn;
fn(); // 立即执行以收集依赖
activeEffect = null;
}
function computed(getter) {
let value;
let dirty = true;
const runner = effect(getter, {
lazy: true,
scheduler() {
dirty = true;
}
});
return {
get value() {
if (dirty) {
value = runner();
dirty = false;
}
return value;
}
};
}
与 Vue 2 的对比
-
Object.defineProperty 的局限性
- 无法检测新增/删除属性
- 对数组操作需要特殊处理
- 需要递归遍历所有属性
-
Proxy 的优势
- 直接拦截对象所有操作
- 完美支持数组变化检测
- 惰性响应式(按需转换)
- 性能更好(无需初始化递归)
实际应用示例
const state = reactive({
count: 0,
todos: []
});
effect(() => {
console.log(`Count is: ${state.count}`);
});
state.count++; // 自动触发日志输出
state.todos.push('Learn Proxy'); // 数组变更也能触发
注意事项
- 原始对象与代理对象不同,应始终使用代理对象
- 嵌套对象需要递归转换为响应式
- 避免在响应式对象中存储非响应式数据
- 浏览器兼容性需要考虑(IE 不支持 Proxy)
通过这种实现方式,可以构建出类似 Vue 3 的响应式系统核心功能,包括数据绑定、计算属性和依赖追踪等特性。







