组合式函数共享响应式状态的关键是确保所有组件访问同一响应式引用:模块级单例+reactive/ref最简,provide/inject适合嵌套场景,需避免解构导致响应式断裂。

在组合式函数中返回响应式状态供多个组件共享,关键不是“返回一个状态”,而是确保所有组件访问的是同一个响应式引用。直接 return reactive 或 ref 是可行的,但是否“共享”取决于调用方式——单例模式才共享,多次调用则各自独立。
用模块级单例 + reactive/ref(最简共享)
适合少量、全局通用的状态(如主题、侧边栏开关、用户基础信息):
- 在 src/stores/globalState.js 中定义并导出一个 模块级响应式对象,利用 ES 模块单例特性保证唯一引用
- 用
reactive管理对象状态(如{ theme: 'light', sidebarOpen: false }),用ref管理简单值(如count = ref(0)) - 组件中直接 import 使用,不要解构赋值(否则丢失响应性),模板里
ref需加.value,reactive可直接访问属性
用 provide/inject + useSharedState(推荐嵌套场景)
适合有明确父子链路、需方法与状态共存的协作场景(如表单上下文、权限会话):
分析 Vue 3 Composition API 使用情况——审计响应式模式、可组合函数设计、ref 与 reactive 的选择、计算属性、watcher 使用及组件……
- 在 src/composables/useSharedState.js 中定义函数,内部创建并返回
reactive对象 - 在顶层组件(如 App.vue)中调用该函数,再通过
provide('shared', shared)注入 - 子组件用
inject('shared')获取——拿到的是原始响应式代理,可读写、可调方法,且保持响应式 -
key 推荐用 Symbol(如
Symbol('shared'))避免命名冲突
封装为带类型提示的组合式函数(兼顾复用与 TS)
当需要支持 TypeScript 自动推导、单元测试或未来扩展多实例时:
- 函数内 return
reactive或多个ref组成的对象(不推荐直接 return reactive 后被解构) - 若需全局唯一,函数本身不 new 实例,而是在外部定义单例并 export;若需多实例(如多个模态框),则每次调用都新建 ref/reactive
- 配合
inject使用时,可用泛型约束类型,例如:inject<returntype usesharedstate>>(storeKey)</returntype>
必须避开的坑
响应式失效几乎都源于引用断裂:
- ❌ 不要对 inject 或 import 的响应式对象做普通解构:
const { count } = shared→ 后续count = 5不触发更新 - ✅ 正确做法:保持对象访问(
shared.count = 5),或用toRefs(shared)解构后仍保留响应性 - ❌ 不要用普通对象包裹 reactive 数据再注入(如
provide('x', { state })),这会切断响应式连接 - ✅ 提供时直接提供 reactive 实例本身,注入后也直接使用它
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









