人人都会AI编程

shallowRef /shallowReactive 浅层响应式

更新时间:2026-07-11

在 Vue 的响应式系统中,refreactive 默认会对数据进行深度代理——当你把一个对象传给 reactive 或通过 .value 赋值给 ref 时,Vue 会递归遍历这个对象的所有属性(包括嵌套的子对象),为每一层都创建响应式代理。

这种“全自动”的深度响应式在 99% 的场景下都是理想的,因为它让你完全不用操心“哪层是响应式的”。但在一些特定场景下,深度代理反而会造成不必要的性能浪费,甚至干扰外部数据。这时就需要用到 浅层响应式 APIshallowRefshallowReactive

shallowRef

shallowRef 创建的响应式引用,只有 .value 本身的替换才是响应式的.value 内部属性的变化不会被追踪。

import { shallowRef } from 'vue'

const state = shallowRef({ count: 0 })

// 触发响应:整个 value 被替换
state.value = { count: 1 }

// 不触发响应:内部属性的变更
state.value.count++ // 视图不会更新

实用场景:

  • 与第三方库集成:当你需要处理一个大型、复杂的对象(比如 ECharts 实例、地图实例、富文本编辑器实例),这些对象有自己的内部状态管理,你完全不需要 Vue 去代理它们的每一个内部属性。使用 shallowRef,只关心“整个实例是否被替换”即可。
  const chartInstance = shallowRef(null)
  // 初始化时赋值
  chartInstance.value = echarts.init(dom)
  // 销毁时直接替换为 null
  chartInstance.value = null
  
  • 大数据列表:如果你的数据是一个包含成千上万条记录的数组,并且你只会整体替换它(比如分页切换时直接替换整个数组),那么 shallowRef 可以避免深度遍历带来的初始化开销和内存消耗。

注意:如果既需要整体替换又需要偶尔修改内部属性,可以手动触发一次依赖更新,比如:

state.value = { ...state.value, count: state.value.count + 1 }

shallowReactive

shallowReactive 创建一个响应式对象,只有对象自身的属性(第一层)是响应式的,嵌套对象的属性不会被代理。

import { shallowReactive } from 'vue'

const state = shallowReactive({
  user: { name: 'Alice' },
  count: 0
})

// 触发响应:第一层属性的整体替换
state.user = { name: 'Bob' }
state.count++

// 不触发响应:深层属性的变更
state.user.name = 'Charlie' // 视图不会更新

实用场景:

  • 表单数据隔离:在大型表单中,你可能只需要监听字段本身的赋值(如 formData.name = 'xx'),而不需要关心复杂嵌套对象内部的变化(因为实际提交时才用到)。使用 shallowReactive 可以避免深层代理的性能消耗。
  • 挂载外部状态:当你把某个外部系统的状态对象挂到组件上,且只希望 Vue 监测这个对象的“引用是否改变”,而不干扰其内部逻辑时,用 shallowReactive 包裹一层即可。

shallowRef 的对比

  • shallowRef 追踪的是 .value 的替换,内部属性完全不响应。
  • shallowReactive 追踪的是第一层属性的增删改,第二层及更深就不管了。

何时使用浅层响应式?

绝大多数业务代码不需要刻意使用 shallowRefshallowReactive——Vue 的深度响应式已经足够快,且能避免“忘记深层次没有响应”的 bug。但当遇到以下情况时,它们就是性能优化的利器:

  1. 需要代理大量数据:比如一个包含数万个节点的地图数据,只需要整体替换而不需要单点修改。
  2. 集成有自身状态管理的外部对象:比如 WebSocket 实例、视频播放器实例、复杂图表实例。
  3. 明确知道某些深层结构不需要响应式:为减少内存和代理开销,在组件内部做精细化控制。

一句话总结:浅层响应式是让开发者对响应式系统的“深度”有了自主控制权——在需要极致性能或与外部系统协作时,你可以选择只让某些层级的变更触发更新,而让其他部分保持“冷静”。但在常规业务开发中,优先使用 refreactive 会更安全、更省心。