Vue 3 + TypeScript 响应式共享状态“失效”的问题根本原因
响应式变量必须是单例,才能在多个地方共享响应式性。
😵💫 现象
你在一个 ts
模块中这样写:
// store.ts
import { ref, watch } from 'vue'
export const count = ref(0)
watch(count, (val) => {
console.log('store 内部监听:', val)
})
然后在另一个地方使用:
// A.vue
import { count } from './store'
watch(count, (val) => {
console.log('组件 A 的监听:', val)
})
结果你发现:
在
store.ts
中的监听正常触发;在其他地方
watch(count, ...)
却监听不到变化?
✅ 根本原因
你可能犯了 “重新创建响应式变量” 的错误,比如:
你不是导出
ref
本身,而是导出一个函数,每次都创建新的ref
你多次导入或者某些环境中有热更新导致
store.ts
被多次执行你用了
defineExpose()
或类似语法暴露变量,但不是响应式的ref
本身
✅ 正确的做法:确保响应式变量是单例!
❗ 错误示例
// ❌ 每次调用 useCount 都创建新的 ref,失去响应式共享
export function useCount() {
return ref(0)
}
✅ 正确示例:使用模块作用域变量
// store.ts
import { ref } from 'vue'
const count = ref(0) // 在模块作用域中定义
export function useCount() {
return {
count
}
}
然后其他地方用:
const { count } = useCount()
watch(count, (val) => {
console.log('组件监听:', val)
})
现在多个地方使用 useCount()
,都会共享同一个 ref
,响应式就生效了!
✅ 最终建议结构(推荐组合式写法)
// stores/useComponentStore.ts
import { ref, computed } from 'vue'
const components = ref([...])
const activeComponent = computed(() => {
return components.value.find(item => item.active)
})
export function useComponentStore() {
return {
components,
activeComponent,
setActiveComponent: (id: string) => {
components.value.forEach(item => item.active = item.id === id)
}
}
}
💡 只要你 export 的变量是在模块作用域创建的,响应式性就能在多个组件中共享。
本作品采用《CC 协议》,转载必须注明作者和本文链接