Proxy代理普通对象可实现简易响应式系统,通过get/set拦截触发依赖收集与更新通知,封装为reactive和effect函数,支持嵌套对象递归代理及数组常用方法劫持。

用 Proxy 代理普通对象实现简易响应式系统,核心是拦截对象的读取(get)和写入(set)操作,在其中触发依赖收集与更新通知。不需要类、也不依赖框架,纯原生 JS 即可完成。
监听属性访问并收集依赖
每次读取属性时,需要知道“谁在读”,也就是当前正在执行的副作用函数(如渲染函数)。我们用一个全局变量临时存贮当前活跃的副作用函数,在 get 拦截中把它和被读取的属性关联起来。
- 维护一个全局的
activeEffect变量,指向当前正在运行的副作用函数 - 每个响应式对象对应一个
Map(key 是属性名,value 是该属性对应的副作用函数 Set) - 在
get中:若activeEffect存在,就把该函数加入对应属性的依赖集合
拦截赋值并触发更新
当某个属性被修改时,就从它对应的依赖集合中取出所有副作用函数并执行,从而实现“数据变 → 视图更新”。
- 在
set拦截中,先执行原赋值逻辑(target[key] = value) - 然后查出该 key 对应的所有副作用函数,依次调用
- 注意区分原始值与对象:对嵌套对象属性赋值时,需确保其本身也是响应式的(递归代理)
封装成 reactive 和 effect 工具函数
把 Proxy 创建和依赖管理封装成易用的 API,模仿 Vue 的基本用法:
立即学习“Java免费学习笔记(深入)”;
-
reactive(obj):返回一个被 Proxy 包裹的响应式对象 -
effect(fn):执行一次fn,并将其作为副作用函数注册进依赖系统 - 内部用
WeakMap缓存已代理的对象,避免重复代理同一对象
处理数组和特殊方法(简化版)
数组的响应式比普通对象更复杂,但简易系统可只覆盖常用方法(push、pop、shift、unshift、splice),或直接监听 length 和索引变化。
- 对数组调用
reactive时,也返回 Proxy,同时重写其变更方法(如push) - 这些方法内部先调用原生方法,再手动触发对应索引和
length的更新 - 不支持
for...in或Object.keys()的自动追踪,需改用Array.prototype.forEach等明确访问索引的操作
不复杂但容易忽略细节:比如 set 返回布尔值表示是否成功,要保留;get 中读取原型链上的属性(如 toString)不应收集依赖;深层嵌套对象要在首次访问时才递归代理,提升性能。


















