Pinia 的 $subscribe 方法用于监听 store 中 state 的变更,比 watch 更轻量且仅在 state 真实修改时触发;它接收 mutation 和 state 参数,支持手动过滤字段、持久化存储及通过返回的取消函数避免内存泄漏。

Pinia 的 $subscribe 方法用于监听仓库(store)中状态(state)的变更,它比直接监听 watch 更轻量、更语义化,且只在 state 真正被修改时触发(不响应 computed 或 getters 变化)。
基本用法:监听整个 store 的 state 变化
在 store 实例上调用 $subscribe,传入一个回调函数。该回调接收两个参数:mutation(描述变更的对象)和 state(变更后的最新 state)。
示例:
import { useCounterStore } from '@/stores/counter'
<p>const counterStore = useCounterStore()</p><p>counterStore.$subscribe((mutation, state) => {
console.log('变更类型:', mutation.type) // 'direct'(直接赋值)或 'patch object' / 'patch function'
console.log('变更路径:', mutation.storeId) // store 的 id,如 'counter'
console.log('当前 state:', state)
})</p><p>// 触发变更
counterStore.count++ // → 触发订阅
</p>
只监听特定字段(通过条件过滤)
$subscribe 本身不提供字段级过滤,但你可以在回调中手动判断变更是否涉及目标字段。推荐检查 mutation.type 和结合当前 state 与上一次快照对比(需自行缓存)。
更实用的做法是:在回调中用 JSON.stringify 或深比较工具对比关键字段:
- 保存上一次相关字段的值(如
lastCount),在每次订阅回调中比对 - 仅当目标字段实际变化时执行业务逻辑(避免冗余响应)
- 注意:不要在回调中直接修改 state,否则可能引发循环调用
持久化场景:配合 $persist 或手动写入 localStorage
常见需求是 state 变化后自动保存到 localStorage。可结合 $subscribe 实现:
counterStore.$subscribe((_, state) => {
localStorage.setItem('counter-state', JSON.stringify({
count: state.count,
name: state.name
}))
})
⚠️ 注意:如果使用了 pinia-plugin-persistedstate,通常无需手动订阅 —— 插件已内部处理。只有自定义持久化逻辑时才需手动 $subscribe。
取消订阅(避免内存泄漏)
$subscribe 返回一个取消函数,组件卸载或不再需要监听时应调用它:
const unsubscribe = counterStore.$subscribe(() => { /* ... */ })
<p>// 在 onUnmounted 或 cleanup 阶段调用
onUnmounted(() => {
unsubscribe()
})
</p>
在 setup 中也可用 onBeforeUnmount 或组合式 API 的生命周期钩子管理。










