如何使用 shallowRef 优化大数据量渲染?显著提升页面性能的干货
shallowRef 不直接优化大数据量渲染,但能避免对大型对象或数组深度响应式代理,减少 Proxy 开销;适用于整体替换场景,如分页加载,不适用于需监听嵌套属性变化的场景。shallowRef 不是用来直接优化大数据量渲染的“银弹”,但它在特定场景下能显著减少不必要的响应式开销,从而间接提升大数据量列表或表格的渲染性能。关键在于:避免对大型普通对象或数组做深度响应式代理。什么时候该用 shallowRef?当你有一个很大的普通 JavaScript 对象(比如包含成百上千个字段的配置项)或超长数组,并且你只打算整体替换它,而不是频繁修改它的内部属性时,shallowRef 就很合适。Vue 的 ref 会对值做 reactive() 处理,而 shallowRef 只让 .value 本身是响应式的,内部结构保持原样——不递归转响应式。? 适合:整个数据集一次性替换(如分页加载新列表、搜索后全量更新) ? 不适合:需要监听 item.name 变化并触发更新的嵌套响应式场景 ?? 注意:v-for 渲染时仍需 key,shallowRef 不解决 key 缺失导致的复用问题对比 ref 和 shallowRef 的实际开销差异假设你有这样一个 10,000 条记录的数组:const largeList = Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `item-${i}`, desc: '...' }))ref(largeList):Vue 会遍历每一项,对每个对象执行 reactive(),产生上万个 Proxy 实例,初始化慢、内存高、GC 压力大 shallowRef(largeList):仅对 largeList 这个数组引用做响应式,内部对象仍是普通 JS 对象,无 Proxy 开销怎么配合 v-for 安全使用?shallowRef 的值变化会触发视图更新,但前提是组件要“读取”到这个响应式引用。确保在模板中正确访问:? 正确:v-for="item in list.value" :key="item.id"(list 是 shallowRef) ? 更推荐:在 setup 中解构为常量 const list = shallowRef(data); const items = computed(() => list.value),模板中直接写 v-for="item in items" ? 错误:直接 const items = list.value 赋值给响应式变量,会丢失响应性进阶技巧:按需 shallow + 局部 reactive如果某些关键字段(如 item.isSelected)确实需要响应式,又不想全量 reactive,可以组合使用:用 shallowRef 管理整个列表 对需要交互的字段单独抽离为 ref 或用 reactive 包裹局部对象 例如:选中状态用 const selectedIds = ref(new Set()),渲染时靠 selectedIds.value.has(item.id) 判断,避免污染原始数据响应性
