📖 概述
shallowRef()
是 Vue 3 中的一个组合式 API 函数,用于创建浅层响应式引用。与ref()
不同,shallowRef()
只在其.value
被直接替换时触发响应式更新,不会深度监听对象内部属性的变化。
🎯 基本概念
什么是 shallowRef?
shallowRef()
创建一个响应式引用,但只在其值被完全替换时触发更新,不会深度监听对象或数组内部的变化。这提供了更好的性能,特别适用于大型对象或不需要深度响应式的场景。
使用场景
- 🚀 性能优化:处理大型对象或数组
- 🎮 游戏开发:频繁更新的状态管理
- 📊 数据可视化:大量数据的响应式处理
- 🔧 第三方库集成:避免深度响应式监听
🔧 函数签名
function shallowRef<T>(value: T): ShallowRef<T>;
interface ShallowRef<T> {
value: T;
}
💻 代码示例
🚀 基础用法
<script setup lang="ts">
import { shallowRef, ref } from "vue";
// 创建浅层响应式引用
const shallowData = shallowRef({ count: 0, name: "Vue" });
const deepData = ref({ count: 0, name: "Vue" });
// 直接替换值会触发更新
shallowData.value = { count: 1, name: "Vue3" };
// 修改内部属性不会触发更新
shallowData.value.count = 2; // ❌ 不会触发响应式更新
// 而 ref 会深度监听
deepData.value.count = 2; // ✅ 会触发响应式更新
</script>
📊 大数据处理
<script setup lang="ts">
import { shallowRef, onMounted } from "vue";
// 大型数据集
const largeDataset = shallowRef([]);
onMounted(async () => {
// 模拟获取大量数据
const data = await fetchLargeDataset();
largeDataset.value = data; // ✅ 一次性更新,性能更好
});
// 批量更新数据
const updateDataset = (newData: any[]) => {
largeDataset.value = newData; // ✅ 触发更新
};
</script>
⚖️ 与 ref 的对比
🔍 深度响应式(ref)
<script setup lang="ts">
import { ref } from "vue";
const user = ref({ name: "Alice", age: 25 });
// 修改内部属性会触发更新
user.value.age = 26; // ✅ 触发响应式更新
user.value.name = "Bob"; // ✅ 触发响应式更新
</script>
🎯 浅层响应式(shallowRef)
<script setup lang="ts">
import { shallowRef } from "vue";
const user = shallowRef({ name: "Alice", age: 25 });
// 修改内部属性不会触发更新
user.value.age = 26; // ❌ 不会触发响应式更新
user.value.name = "Bob"; // ❌ 不会触发响应式更新
// 只有完全替换对象才会触发更新
user.value = { name: "Bob", age: 26 }; // ✅ 触发响应式更新
</script>
⚠️ 注意事项
🔄 触发更新的方式
shallowRef
只在以下情况触发响应式更新:
<script setup lang="ts">
import { shallowRef } from "vue";
const data = shallowRef({ count: 0 });
// ✅ 会触发更新
data.value = { count: 1 };
// ❌ 不会触发更新
data.value.count = 1;
data.value.nested = { value: 1 };
</script>
🎯 与 reactive 的区别
shallowRef
和shallowReactive
的区别:
<script setup lang="ts">
import { shallowRef, shallowReactive } from "vue";
// shallowRef - 需要 .value 访问
const refData = shallowRef({ count: 0 });
console.log(refData.value.count);
// shallowReactive - 直接访问
const reactiveData = shallowReactive({ count: 0 });
console.log(reactiveData.count);
</script>
🔧 手动触发更新
如果需要手动触发更新,可以使用
triggerRef
:
<script setup lang="ts">
import { shallowRef, triggerRef } from "vue";
const data = shallowRef({ count: 0 });
// 修改内部属性
data.value.count = 1;
// 手动触发更新
triggerRef(data); // ✅ 强制触发响应式更新
</script>
🎯 最佳实践
1️⃣ 性能优化场景
在需要处理大型对象或频繁更新的场景中使用:
<script setup lang="ts">
import { shallowRef, computed } from "vue";
// 大型配置对象
const config = shallowRef({
theme: "dark",
language: "zh-CN",
settings: {
/* 大量配置项 */
},
});
// 只在配置完全替换时更新
const updateConfig = (newConfig: typeof config.value) => {
config.value = newConfig;
};
</script>
2️⃣ 避免不必要的深度监听
当不需要监听对象内部变化时使用:
<script setup lang="ts">
import { shallowRef } from "vue";
// 只关心整体替换,不关心内部变化
const userProfile = shallowRef({
id: 1,
name: "Alice",
preferences: { theme: "dark", notifications: true },
});
// 更新整个用户资料
const updateProfile = (profile: typeof userProfile.value) => {
userProfile.value = profile;
};
</script>
3️⃣ 结合 triggerRef 使用
在需要精确控制更新时机时:
<script setup lang="ts">
import { shallowRef, triggerRef } from "vue";
const formData = shallowRef({
name: "",
email: "",
message: "",
});
// 批量更新后手动触发
const updateForm = (updates: Partial<typeof formData.value>) => {
Object.assign(formData.value, updates);
triggerRef(formData); // 手动触发更新
};
</script>
❓ 常见问题
Q: 什么时候使用 shallowRef 而不是 ref?
A: 当处理大型对象、频繁更新的数据,或不需要深度响应式监听时使用 shallowRef。
Q: shallowRef 会影响计算属性吗?
A: 计算属性会正常响应 shallowRef 的变化,但不会响应其内部属性的变化。
Q: 如何强制 shallowRef 更新?
A: 使用
triggerRef()
函数可以强制触发 shallowRef 的响应式更新。
📝 总结
shallowRef()
是 Vue 3 中用于性能优化的强大工具,特别适用于处理大型对象、频繁更新的状态,以及不需要深度响应式监听的场景。通过合理使用shallowRef()
,可以显著提升应用性能,同时保持必要的响应式能力。记住,只有在完全替换值时才会触发更新,如需手动控制更新时机,可以使用triggerRef()
。
原文链接:https://code.ifrontend.net/archives/1077,转载请注明出处。
评论0