Vue3响应式基于Proxy实现,通过get拦截器收集依赖、set拦截器触发更新,并用has/ownKeys/deleteProperty等补全边界场景,克服Object.defineProperty无法监听新增属性、数组索引变化等缺陷。

Vue 3 的响应式不是靠“监视每个属性”,而是给整个对象装了个智能门卫——Proxy。它不改原始数据,只在你读、写、删、遍历的时候悄悄插一脚,把操作拦下来,干两件事:记一笔“谁在用这个值”,改的时候喊一嗓子“你们用的值变了”。
get 拦截器:读取时自动记录依赖
你在模板里写 {{ state.count }},或代码中访问 state.name,就会触发 get 拦截器。它实际做三件事:
- 调用 track():检查当前是否有正在运行的副作用(比如组件 render 函数、watch 回调、computed),有就把它加入该字段专属的依赖集合;
- 递归代理嵌套对象:如果读到的是一个对象(如 state.user),就对它也套一层 Proxy,确保深层属性也能响应;
- 用 Reflect.get() 正常返回值,整个过程对你完全透明。
set 拦截器:修改时立刻通知所有依赖
执行 state.count++ 或 state.msg = 'hello' 时,set 就被触发。它核心就两步:
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 调用 trigger():根据 target(对象)和 key(字段名),查出之前 track 存下的所有依赖(比如 A 组件、B 计算属性、C watch);
- 挨个执行这些依赖:相当于喊:“count 变了,快重跑一遍!”——组件重新渲染、computed 重新求值、watch 回调再次触发。
其他拦截器:补全边界场景,让响应式无死角
光靠 get/set 不够,Vue 还用多个小拦截器兜底:
立即学习“前端免费学习笔记(深入)”;
- has(key):拦截 'name' in state,确保判断属性是否存在时也能收集依赖;
- ownKeys():拦截 Object.keys(state) 或 for...in,为整个对象的“键列表”单独设一个特殊标记(ITERATE_KEY),这样遍历时也能建立依赖;
- deleteProperty(key):拦截 delete state.age,删完立刻 trigger,让依赖它的逻辑知道“这个字段没了”。
为什么 Proxy 比 Object.defineProperty 更强?
Vue 2 的 Object.defineProperty 是“逐个属性安装监听器”,而 Vue 3 的 Proxy 是“给整个对象加一层壳”。这带来三个关键提升:
- 新增属性无需 Vue.set,直接 state.newKey = 1 就能响应;
- 数组索引赋值(arr[0] = 999)、length 修改、甚至原生方法(push/pop/splice)天然支持,不用额外重写;
- 初始化性能更好:不需要递归遍历所有属性,只在真正访问时才代理,按需响应。

















