shallowref适用于大对象整体替换场景,仅响应.value赋值,不深层代理嵌套属性,配合triggerref可手动触发更新,显著提升性能。

直接用 shallowRef 替代 ref 处理大对象,能跳过深层代理,大幅减少 Proxy 创建、依赖收集和内存占用——关键不是“不用响应式”,而是只在需要时才触发更新。
什么情况该换 shallowRef
当你的对象满足以下任意一条,就适合改用 shallowRef:
- 数据量大(比如 5000+ 条用户、上万点图表原始数据),但业务逻辑只做整体替换,不修改内部字段
- 对象来自第三方库(如 ECharts 实例、Mapbox 地图、Three.js 场景),你只关心“整个实例被换掉”这个动作
- 后端返回的是不可变 JSON,前端只读或仅批量重赋值,不逐个改
item.profile.phone这类嵌套属性 - 模板里只用到
{{ config.theme }}或v-for="item in list",没写{{ item.meta.permissions[0].action }}这种深层访问
怎么写才真正起效
光声明 shallowRef 不够,赋值和更新方式必须配合:
- 初始化:用
const bigData = shallowRef({ items: [] }),别再用ref({ items: [] }) - 整体替换:直接赋新对象,
bigData.value = newData—— 这会触发视图更新 - 误改了内部属性?比如
bigData.value.items.push(...),Vue 不响应 → 此时手动调triggerRef(bigData)强制刷新 - 避免在模板或 computed 中写深层链式访问;如果真要用,提前用
computed暴露成顶层字段,例如const userName = computed(() => bigData.value?.user?.name)
和 markRaw、reactive 怎么区分用
它们解决的问题不同,别混用:
-
shallowRef:要保留
.value语法,且数据可能含基础类型 + 对象混合(比如{ count: 1, data: [...] }) -
markRaw:对象完全静态或只读(如配置项、枚举表),连
.value都不需要,直接const conf = markRaw({ api: '/v1' }) -
shallowReactive:纯对象,想省掉
.value,但又不希望 Vue 递归代理嵌套结构(比如表单状态{ name: '', address: { city: '' } })
实际项目中,合理使用 shallowRef 后,5000 条扁平列表挂载耗时可降 40%~60%,大型可视化组件初始化卡顿明显缓解。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










