Proxy 是实现双向绑定响应式的核心机制,通过拦截 get/set 操作收集依赖并触发更新,需递归代理嵌套对象、特殊处理数组方法,并配合 effect 实现自动依赖追踪与 DOM 双向同步。

Proxy 可以拦截对象的读写操作,从而在数据变化时自动触发更新,是实现双向绑定响应式的核心机制之一。关键在于用 get 拦截取值、用 set 拦截赋值,并在其中收集依赖、触发更新。
用 Proxy 拦截 get/set 实现响应式基础
通过 new Proxy(target, handler) 包裹原始对象,重写 get 和 set 行为:
-
get中调用依赖收集函数(如track(target, key)),把当前正在执行的副作用函数(如渲染函数)与该属性关联起来; -
set中先更新值,再调用触发更新函数(如trigger(target, key)),通知所有依赖该属性的函数重新执行; - 注意:对嵌套对象也要递归代理,否则深层属性修改不会被拦截(可用
reactive函数递归处理)。
配合 effect 实现自动依赖追踪
单独 Proxy 不知道“谁在读这个值”,需要一个响应式运行时上下文来记录当前活跃的副作用函数:
- 定义全局变量
activeEffect,在执行副作用函数前临时赋值; -
track()把activeEffect存入以(target, key)为键的依赖 Map 中; -
trigger()查找对应依赖并逐个执行; - 这样写
effect(() => console.log(obj.count))就会在obj.count = 5时自动重跑。
处理数组和特殊方法(push/pop 等)
Proxy 默认无法拦截数组索引赋值(如 arr[0] = x)或原生方法(如 push),需额外处理:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 对数组,
set拦截中判断是否为数字索引,是则触发更新; - 对
length变更或增删方法,可重写数组原型上的方法(如用proxy.push = function(...args) { ... }),并在内部手动调用trigger; - 更稳妥的做法是:检测到数组后,用
Array.prototype方法增强 + 拦截set+ 特殊处理length。
与 DOM 绑定实现双向更新(v-model 类似逻辑)
将响应式对象与表单元素联动,需监听输入事件并同步更新数据:
- 给
<input v-model="msg">绑定input事件,事件回调中执行data.msg = $event.target.value; - 由于
data是 Proxy 对象,set被拦截 → 触发依赖更新 → 渲染函数重执行 → 视图刷新; - 同时,在
get中读取data.msg时完成依赖收集,保证后续修改能驱动视图; - 注意避免循环更新:输入框 value 更新应只由数据驱动,不直接操作 DOM value 属性(除非必要)。
不复杂但容易忽略细节,比如嵌套代理、数组方法劫持、依赖清理(避免内存泄漏)、以及 effect 嵌套时的栈管理。Vue 3 的 reactive 和 effect 就是基于这套思路构建的。

















