Proxy可通过拦截set和get实现响应式观察者模式:set拦截赋值并触发回调,get拦截访问并自动收集依赖;需维护属性到回调的映射、处理嵌套对象与数组、避免无限递归。

Proxy 可以通过拦截对象的属性读写操作,实现轻量级的观察者模式。核心在于用 set 拦截赋值、用 get 拦截访问,并在变化时触发订阅的回调函数。
用 Proxy 拦截 set 实现响应式更新
每次给目标对象赋值时,set 陷阱能捕获变更,检查是否真正修改了值(避免重复触发),再通知所有监听该属性的回调:
- 需要维护一个“属性 → 回调列表”的映射(如
Map<string array>></string>) - 在
set中先执行原操作(Reflect.set()),再判断是否变更成功 - 若变更生效,调用对应属性的所有监听函数,并传入新旧值
- 注意:要避免无限递归(比如回调里又改同一属性),可加防抖或标记位
用 get 拦截自动收集依赖
在读取属性时,get 陷阱可以记录当前正在执行的副作用函数(如渲染函数),将其加入该属性的监听列表:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 需配合一个全局变量(如
activeEffect)暂存当前正在运行的回调 -
get中若activeEffect存在,就把它加入该 key 对应的依赖集合 - 这样数据被读时自动“订阅”,修改时自动“通知”,形成依赖追踪闭环
- 实际开发中常封装为
track(key)和trigger(key)两个辅助函数
支持嵌套对象与数组的注意事项
Proxy 默认只代理第一层,深层属性变更不会触发 set;数组索引赋值(如 arr[0] = x)会被拦截,但 push、pop 等方法不会:
立即学习“Java免费学习笔记(深入)”;
- 对嵌套对象,可在
get返回值前递归代理(返回createReactive(obj)) - 对数组,需重写部分原型方法(如
push),或统一用splice等可拦截的方式 - 也可结合
Reflect.ownKeys+has拦截,处理 in 操作符和 for...in - 避免代理非对象类型(null、原始值),需提前判断
简易可运行示例
以下是一个最小可用的响应式对象封装:
function observe(obj, callbacks = new Map()) {
return new Proxy(obj, {
get(target, key) {
// 收集依赖(需外部设置 activeEffect)
if (activeEffect && typeof key === 'string') {
let deps = callbacks.get(key) || new Set();
deps.add(activeEffect);
callbacks.set(key, deps);
}
const val = target[key];
return typeof val === 'object' && val !== null ? observe(val, callbacks) : val;
},
set(target, key, newVal) {
const oldVal = target[key];
const ret = Reflect.set(target, key, newVal);
if (oldVal !== newVal) {
const deps = callbacks.get(key);
if (deps) deps.forEach(fn => fn(newVal, oldVal));
}
return ret;
}
});
}
// 使用方式:
let state = observe({ count: 0 });
let activeEffect = (val) => console.log('count changed to:', val);
// 手动触发依赖收集(模拟 Vue 的 effect)
state.count; // 触发 get,收集 activeEffect
state.count = 1; // 输出:count changed to: 1

















