组合式函数中暴露 shallowRef 应直接返回实例本身,不使用 toRefs 或解构,以保持浅层响应式特性;需手动更新时可导出 triggerRef 辅助方法。

在组合式函数中暴露 shallowRef 创建的浅层状态,核心原则是:**只返回 .value 可读可写引用本身,不进行 reactive 包装或 toRefs 解构**。否则会破坏 shallowRef 的浅层特性——一旦被 toRefs 或 reactive 处理,内部对象就可能被深度代理,失去性能优化意义。
直接返回 shallowRef 实例
最稳妥、最推荐的方式:组合式函数内部创建 shallowRef,然后原样 return,由调用方自行访问 .value。
- ✅ 保持响应式层级纯净:调用组件拿到的是原始 shallowRef 对象,.value 修改触发更新,深层属性修改不触发
- ✅ 避免意外代理:不经过任何中间转换,第三方实例(如 ECharts、MapLibre)能完整保留原型链与私有状态
- 示例:
export function useMapInstance() {
const map = shallowRef(null)
function init(dom) {
map.value = new MapLibreGL({ container: dom })
}
return { map, init } // 直接返回 shallowRef 实例
}
不推荐:解构或 toRefs
若在组合式函数内对 shallowRef 做 toRefs 或结构赋值,会导致 Vue 尝试对其 value 内部做响应式处理,尤其当 value 是对象时,极易触发深度代理。
- ❌ 错误写法:
return toRefs({ map })或const { map } = useMapInstance()(在 setup 中直接解构) - ❌ 后果:Vue 会对 map.value(即 MapLibreGL 实例)执行 reactive(),引发卡顿、内存暴涨甚至 TypeError
- ⚠️ 注意:即使 value 是原始类型(如 number),toRefs 也不会出错,但已违背 shallowRef 设计意图,且丧失统一语义
需要手动触发更新时,一并暴露 triggerRef
当组合式函数内部需支持“修改深层属性 + 强制刷新”逻辑时,可将 triggerRef 作为辅助方法导出,避免调用方重复 import。
从零开始编排 SpringBoot+Vue 全栈项目工作流,适用于新建全栈项目或完整脚手架请求,触发后依次调用 product‑spec‑builder(需求调研)等模块。
立即学习“前端免费学习笔记(深入)”;
- ✅ 示例:
const data = shallowRef([])
function updateItem(id, field, value) {
const item = data.value.find(i => i.id === id)
if (item) item[field] = value // 深层修改,不触发响应
triggerRef(data) // 主动通知更新
}
return { data, updateItem }
}
模板中使用方式保持不变
在调用组件的 template 里,仍按常规写法访问:{{ state.value?.user?.name }} 或 v-if="state.value"。不需要额外语法,也不建议用 toRaw 包裹——shallowRef 的 value 本身就是原始值,无需解包。
- ✅ 正确:
<p>{{ user.value?.name }}</p> - ❌ 多余:
<p>{{ toRaw(user.value)?.name }}</p>(toRaw 对 shallowRef.value 无实际作用)

















