在 setup 中结合 Pinia 实现跨组件通信,核心是通过 useXXXStore() 获取 store 实例,用 storeToRefs 解构 state 保持响应式,调用 actions 修改状态,通过 computed 或 getters 访问派生状态,避免直接解构导致响应式丢失。
在 setup 中结合 Pinia 实现跨组件通信,核心是让组件通过 Store 实例读取和修改共享状态,同时保持响应式。它不依赖 props 或事件链,而是直接对接集中管理的 state、actions 和 getters,适合中大型 Vue3 项目。
推荐使用组合式 API 风格的 Store 调用方式,配合 storeToRefs 保证响应式不丢失:
useXXXStore() 获取 store 实例(如 useUserStore())storeToRefs() 解构 state 中的响应式属性,避免失去响应性computed 或 getters 访问派生状态(如 store.totalCount)示例:
import { defineComponent, computed } from 'vue'import { useCartStore } from '@/stores/cart'import { storeToRefs } from 'pinia'export default defineComponent({setup() {const cartStore = useCartStore()const { items } = storeToRefs(cartStore) // 保持响应式const totalPrice = computed(() => cartStore.totalPrice) // 使用 getterconst addToCart = (item) => cartStore.addItem(item)return { items, totalPrice, addToCart }}})直接解构 store.state 属性会切断响应式连接,必须用 storeToRefs 或 toRefs 包装:
const { items } = useCartStore() → items 变成普通对象,更新不触发视图刷新const { items } = storeToRefs(useCartStore()) → 保留 ref 响应性const items = computed(() => cartStore.items),但性能略低(每次访问都触发 getter)一个组件常需接入多个 store,可按需引入并统一管理:
useUserStore() + useThemeStore()
userStore.login() 内部调用 themeStore.setByRole(user.role)
当需要监听 store 状态变化执行副作用(如日志、请求、路由跳转),推荐两种方式:
watch 监听具体 ref:watch(() => userStore.token, handleAuthChange)
store.$subscribe 监听所有 state 变更(带 patch 操作类型):cartStore.$subscribe((mutation) => { console.log(mutation.type) })
unsubscribe,或用 onBeforeUnmount 清理