核心是按需响应而非全量劫持:用 shallowRef/shallowReactive 控制响应深度,冻结静态数据,拆分计算与副作用,主动清理失效依赖。

核心思路是让响应式系统“少干活”——不是删数据,而是控制哪些数据该进响应式、哪些不该进,以及进之后怎么被追踪。
用 shallowRef / shallowReactive 替代 deep 响应式
深层嵌套对象默认会触发 Proxy 递归代理,每一层访问都可能触发 track,造成依赖层层挂载。对只读或仅需顶层响应的场景,直接降级:
- shallowRef:ref 的值本身响应,但内部属性不响应(适合存大型 JSON、配置对象)
- shallowReactive:仅代理第一层属性,嵌套对象/数组保持原始状态(适合表格行数据、表单字段集合)
- 注意:修改 shallow 对象的嵌套属性不会触发更新,需配合 triggerRef 或手动调用 update 才能刷新视图
冻结无需响应的数据结构
静态列表、枚举、字典类数据一旦初始化就不再变更,完全没必要参与依赖收集:
- Vue 3 中可用 Object.freeze() 包裹后赋值给 ref 或 reactive —— Proxy 会跳过冻结对象,不建立 getter/setter,自然不收集依赖
- 也可用 readonly() + toRaw() 组合,在需要时临时解构读取,避免意外修改
- 常见误用:把整个 API 响应结果直接 reactive,其中大量元信息(如 timestamp、version)其实从不用于渲染,应提前剔除或冻结
拆分响应式与计算逻辑,避免副作用污染
effect 内部若混入非响应式操作(如 DOM 查询、定时器、第三方库调用),不仅拖慢执行,还可能因异常中断导致依赖收集错乱或残留:
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
立即学习“前端免费学习笔记(深入)”;
- 把纯计算逻辑(如格式化、过滤、映射)抽离为普通函数,输入响应式数据,输出新对象 —— 新对象不进响应式系统,不产生额外依赖
- 副作用操作(如 localStorage 写入、事件监听绑定)移到 onMounted 或 watch 回调中,与 effect 解耦
- 避免在 computed 中做深克隆、JSON.stringify 等高开销操作;改用 memoized 工具函数缓存结果
主动清理失效依赖,防止闭包滞留
组件卸载或条件分支切换时,未清理的 effect 仍持有对旧响应式对象的引用,会导致依赖链冗余甚至内存泄漏:
- 使用 onScopeDispose 注册清理函数,显式调用 stop() 停止不需要的 effect
- watch 和 watchEffect 默认绑定当前组件作用域,但若手动创建 effect(如 useMouse、useTimeout 封装),需确保 unmount 时释放
- 对动态生成的响应式对象(如通过 map 创建的 itemRefs),在 remove 操作后及时 delete 对应 ref,避免空引用持续被 track
不复杂但容易忽略,关键在“按需响应”,而不是“全量劫持”。

















