shallowRef
和 ref
都是 Vue 3 的响应式 API,它们的主要区别在于响应式的深度:
ref
- 深度响应式:会自动递归地将所有嵌套属性都转为响应式
- 适用于:需要完全响应式的复杂对象
javascript
import { ref } from 'vue'
const state = ref({
user: {
name: 'John',
address: {
city: 'New York',
street: '123 Main St'
}
}
})
// 所有这些修改都会触发响应式更新
state.value.user.name = 'Jane' // 触发更新
state.value.user.address.city = 'Boston' // 触发更新
shallowRef
- 浅层响应式 :只对
.value
本身的变化进行响应,不递归转换嵌套属性 - 适用于:大型对象或不需要深度响应的场景,性能更好
javascript
import { shallowRef } from 'vue'
const state = shallowRef({
user: {
name: 'John',
address: {
city: 'New York',
street: '123 Main St'
}
}
})
// 只有这些会触发响应式更新
state.value = { ... } // 直接替换整个值,触发更新
// 这些不会触发响应式更新!
state.value.user.name = 'Jane' // 不触发更新
state.value.user.address.city = 'Boston' // 不触发更新
使用场景对比
ref 适用场景:
javascript
// 需要深度响应的表单数据
const formData = ref({
personalInfo: {
name: '',
age: ''
},
preferences: {
theme: 'light',
notifications: true
}
})
shallowRef 适用场景:
javascript
// 大型不可变数据,只需要整体替换
const largeData = shallowRef({ /* 大量数据 */ })
// 第三方库实例,不需要响应式
const mapInstance = shallowRef(null)
// 性能敏感场景
const heavyObject = shallowRef({ /* 复杂嵌套对象 */ })
强制触发更新
如果需要让 shallowRef
的嵌套属性变化触发更新:
javascript
const state = shallowRef({ count: 0 })
// 方法1:整体替换
state.value = { ...state.value, count: 1 }
// 方法2:使用 triggerRef
import { triggerRef } from 'vue'
state.value.count = 1
triggerRef(state) // 手动触发更新
总结
- ref:深度响应式,适合需要完全响应性的数据
- shallowRef:浅层响应式,性能更好,适合大型对象或只需要整体替换的场景
选择哪个取决于你对数据响应式深度的需求和性能考虑。