在 Vue 中,ref
和 shallowRef
都是用于创建响应式引用的 API,但它们的响应式深度和适用场景有显著区别。以下是两者的详细对比:
1. 核心区别:响应式深度
ref
:深层响应式
对值进行递归监听,无论是基本类型还是对象/数组,修改其内部属性(如对象的属性、数组的元素)都会触发响应式更新。shallowRef
:浅层响应式
仅监听.value
的直接赋值,不追踪对象/数组内部属性的变化,修改内部属性不会触发更新。
2. 使用示例对比
场景1:处理基本类型(数字、字符串等)
两者表现一致,因为基本类型没有内部属性:
// ref
const countRef = ref(0)
countRef.value++ // 触发更新// shallowRef
const countShallowRef = shallowRef(0)
countShallowRef.value++ // 触发更新(与ref一致)
场景2:处理对象/数组
两者行为差异明显:
// ref(深层响应式)
const objRef = ref({ count: 0 })
objRef.value.count++ // 触发更新(内部属性变化被监听)// shallowRef(浅层响应式)
const objShallowRef = shallowRef({ count: 0 })
objShallowRef.value.count++ // 不触发更新(内部属性变化不被监听)
objShallowRef.value = { count: 1 } // 触发更新(直接替换.value)
3. 手动触发更新的差异
shallowRef
可以通过triggerRef
强制触发更新(即使只修改了内部属性):
const data = shallowRef({ count: 0 })
data.value.count++ // 不触发更新
triggerRef(data) // 手动触发更新,视图刷新
ref
无需手动触发,内部属性变化会自动更新。
4. 性能与适用场景
特性 |
|
|
响应式深度 | 深层(递归监听) | 浅层(仅监听 |
性能开销 | 较高(递归追踪所有属性) | 较低(仅追踪顶层) |
适用场景 | 需监听内部属性变化的对象/数组 | 大型数据、无需深层监听的场景 |
典型用例 | 表单数据、业务对象 | 图表数据、大型列表、静态数据 |
5. 总结:如何选择?
- 优先用
ref
:
大多数场景下(尤其是需要监听对象/数组内部变化时),ref
的自动深层响应式更符合直觉,无需手动处理更新。 - 用
shallowRef
优化性能:
当处理大型数据(如包含 thousands 条记录的列表、复杂图表配置)或无需追踪内部变化的数据时,shallowRef
能减少响应式系统的开销,提升性能。 - 注意:
shallowRef
需要手动管理内部属性的更新(通过triggerRef
),过度使用可能导致逻辑复杂,建议仅在明确有性能问题时使用。