欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > shallowRef和shallowReactive的用法以及使用场景和ref和reactive的区别

shallowRef和shallowReactive的用法以及使用场景和ref和reactive的区别

2025/1/31 18:31:09 来源:https://blog.csdn.net/qq_34645412/article/details/145366836  浏览:    关键词:shallowRef和shallowReactive的用法以及使用场景和ref和reactive的区别

Vue3 浅层响应式 API

1. ref vs shallowRef

1.1 基本概念

  • ref: 深层响应式,会递归地将对象的所有属性转换为响应式
  • shallowRef: 浅层响应式,只有 .value 的改变会触发更新,不会递归转换对象的属性

1.2 使用对比

// ref 示例
const deepRef = ref({count: 0,nested: {value: 'hello'}
})// 这些修改都会触发更新
deepRef.value.count++  // 触发更新
deepRef.value.nested.value = 'world'  // 触发更新// shallowRef 示例
const shallowValue = shallowRef({count: 0,nested: {value: 'hello'}
})// 只有直接替换 .value 才会触发更新
shallowValue.value.count++  // 不会触发更新
shallowValue.value.nested.value = 'world'  // 不会触发更新
shallowValue.value = { count: 1 }  // 触发更新

1.3 性能优化示例

<template><div><video ref="videoRef" :src="videoUrl"></video><button @click="updateVideoUrl">更新视频</button></div>
</template><script setup>
import { shallowRef } from 'vue'// 使用 shallowRef 优化大型数据或 DOM 引用
const videoRef = shallowRef(null)
const videoUrl = shallowRef('https://example.com/video.mp4')const updateVideoUrl = () => {// 直接更新 .value 触发更新videoUrl.value = 'https://example.com/new-video.mp4'
}
</script>

2. reactive vs shallowReactive

2.1 基本概念

  • reactive: 深层响应式,递归地将所有嵌套对象转换为响应式
  • shallowReactive: 浅层响应式,只将对象的第一层属性转换为响应式

2.2 使用对比

// reactive 示例
const deepState = reactive({count: 0,nested: {value: 'hello'}
})// 这些修改都会触发更新
deepState.count++  // 触发更新
deepState.nested.value = 'world'  // 触发更新// shallowReactive 示例
const shallowState = shallowReactive({count: 0,nested: {value: 'hello'}
})// 只有第一层属性的改变会触发更新
shallowState.count++  // 触发更新
shallowState.nested.value = 'world'  // 不会触发更新
shallowState.nested = { value: 'world' }  // 触发更新

2.3 实际应用示例

<template><div><h2>用户信息</h2><div>姓名: {{ userInfo.name }}</div><div>年龄: {{ userInfo.age }}</div><!-- 不需要追踪 metadata 的变化 --><div>元数据: {{ userInfo.metadata.lastUpdated }}</div></div>
</template><script setup>
import { shallowReactive } from 'vue'// 使用 shallowReactive 优化性能,metadata 的变化不需要触发更新
const userInfo = shallowReactive({name: 'John',age: 30,metadata: {lastUpdated: new Date(),visits: 0}
})// 只有顶层属性的变化会触发更新
const updateUser = () => {userInfo.name = 'Jane'  // 触发更新userInfo.metadata.visits++  // 不会触发更新
}
</script>

3. 使用场景对比

3.1 适合使用深层响应式(ref/reactive)的场景

  1. 表单数据
const formData = reactive({user: {name: '',email: '',preferences: {newsletter: true,notifications: {email: true,sms: false}}}
})
  1. 需要监听所有层级变化的数据
const settings = ref({theme: {dark: false,colors: {primary: '#000',secondary: '#fff'}}
})

3.2 适合使用浅层响应式(shallowRef/shallowReactive)的场景

  1. 大型数据结构且只需要监听顶层变化
const bigData = shallowRef({items: new Array(10000).fill(0).map((_, i) => ({id: i,data: { /* 大量数据 */ }}))
})// 整体替换数据时才触发更新
const updateData = () => {bigData.value = newBigData
}
  1. 外部库或 DOM 引用
const chartInstance = shallowRef(null)
const mapInstance = shallowRef(null)onMounted(() => {chartInstance.value = new ThirdPartyChart()mapInstance.value = new ThirdPartyMap()
})
  1. 不需要深层响应式的状态管理
const state = shallowReactive({ui: {loading: false,error: null},cache: new Map(), // 不需要响应式的缓存数据helpers: {formatter: () => {}, // 工具函数不需要响应式}
})

4. 性能优化建议

  1. 选择合适的响应式 API
// ✅ 大型数据使用浅层响应式
const bigData = shallowRef(largeDataSet)// ❌ 不必要的深层响应式
const bigData = ref(largeDataSet)
  1. 避免不必要的响应式转换
// ✅ 静态数据使用浅层响应式
const config = shallowReactive({constants: { /* 大量静态配置 */ },settings: { /* 需要响应式的设置 */ }
})// ❌ 对静态数据使用深层响应式
const config = reactive({constants: { /* 大量静态配置 */ },settings: { /* 需要响应式的设置 */ }
})
  1. 合理组合使用
// 混合使用深层和浅层响应式
const state = reactive({// 需要深层响应式的数据userSettings: {theme: 'dark',notifications: { /* ... */ }},// 使用 shallowRef 包装大型数据bigData: shallowRef(largeDataSet)
})

5. 注意事项

  1. 响应式丢失问题
const shallow = shallowReactive({nested: {count: 0}
})// 解构会失去响应性
const { nested } = shallow
nested.count++ // 不会触发更新
  1. 替换整个对象
const data = shallowRef({nested: {value: 0}
})// 需要替换整个对象才能触发更新
data.value = {nested: {value: 1}
}
  1. 与计算属性配合
// 当只需要监听部分数据变化时,使用计算属性
const data = shallowReactive({items: [],metadata: { /* ... */ }
})// 只监听 items 的变化
const computedValue = computed(() => {return processItems(data.items)
})

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com