Pinia的store里怎么监听其他store的状态变化?
我有两个Pinia store,userStore和cartStore。现在想在cartStore里监听userStore里的userId变化,一旦变了就重新拉购物车数据。试过用watch,但好像没生效,是不是写法不对?
我的代码大概是这样:
import { defineStore } from 'pinia'
import { userStore } from './user'
export const cartStore = defineStore('cart', () => {
const user = userStore()
watch(() => user.userId, (newId) => {
if (newId) fetchCart(newId)
})
return { /* ... */ }
})
但页面加载时watch根本不触发,切换用户也没反应,是不是Pinia里不能这么用?
userStore()获取实例时,store 还没完全初始化好,所以 watch 根本绑不到正确的响应式数据上。先说为什么你的写法不行:
你写的是 setup 语法(箭头函数形式),在这个函数执行的时候,userStore 还没有被创建出来。你调用
userStore()拿到的确实是个 store 实例,但这个实例里面的状态不是响应式的——因为 Pinia 还没开始追踪它。正确的写法有几种:
第一种,用
storeToRefs把需要监听的状态提取成响应式 ref:第二种,用 computed 包装一下再监听:
第三种,用 Pinia 提供的
$subscribe,这是最官方的跨 store 监听方式:$subscribe的好处是它只会触发状态真正变化的时候,不会重复触发,而且能拿到 mutation 信息。再补充一点:
如果你想在页面加载时也触发一次(不只是 userId 变化时),可以这样:
这几种方案都能解决你的问题,推荐用第一种
storeToRefs的方式,代码最清晰。userStore()拿到的实例响应式会丢失。Pinia 的 setup 语法里要监听另一个 store,得用storeToRefs或者在 watch 回调里重新获取 store。给你两种改法:
第一种,用 storeToRefs 保持响应式:
第二种,更简单,直接在 watch 里调用:
第二种写法更省心,不用担心响应式丢失的问题,我平时更喜欢这么写。
另外记得在 cartStore 里也声明 fetchCart 这个函数,或者直接调用外部的接口方法。