用 reactive 实现跨组件状态共享的核心是将响应式对象定义在模块顶层,通过直接导入或 provide/inject 使用;需用 toRefs 解构保持响应性,并推荐封装操作函数提升可维护性。
在简单场景下,用 reactive 实现跨组件状态共享,核心思路是:把响应式对象定义在模块顶层(非组件内部),再通过 provide/inject 或直接导入使用,避免引入 Pinia/Vuex 这类重型方案。
在单独文件(如 store.ts)中创建并导出 reactive 对象:
import { reactive } from 'vue'
export const sharedState = reactive({
theme: 'light',
user: { name: '', id: 0 },
cartItems: [] as Product[]
});
这个对象本身是响应式的,所有导入它的组件都能实时感知变化。
在任意组件中:
import { sharedState } from '@/store'
模板中直接用 {{ sharedState.theme }},逻辑中直接改 sharedState.user.name = 'Alice'。无需 setup 或 provide,简单直接。
在根组件(如 App.vue)的 setup 中:
provide('shared', sharedState)
子组件中:
const shared = inject('shared') as typeof sharedState
这样能避免全局污染,也便于测试和替换。
如果想在组件中解构使用(比如只用 theme 和 user),不能直接写:
const { theme, user } = sharedState // ❌ 响应性丢失
正确做法是用 toRefs:
import { toRefs } from 'vue'
const { theme, user } = toRefs(sharedState) // 保持响应式
return { theme, user }
这样模板里就能写 {{ theme }} 而不是 {{ sharedState.theme }},更简洁。
不建议直接暴露裸对象修改,推荐在 store 文件中一并导出操作函数:
export function setTheme(newTheme: string) {
sharedState.theme = newTheme;
}
export function addUser(name: string) {
sharedState.user = { name, id: Date.now() };
}
组件中调用 setTheme('dark'),语义清晰,后续加日志、校验或持久化也容易扩展。