有点标题党,实际上解决的$subscribe.mutation.events中 变化的key无法的得知的问题
vue3的项目中,使用pinia做状态管理,如果想要在组件中监听state中变化,可以使用 $subscribe做监听。
// store/app.ts
interface AppState {
theme: string,
[key: string]: any
}
export const useAppStore = defineStore('app', {
state(): AppState {
return {
theme: 'dark'
}
},
actions: {
setTheme(theme: string) {
this.theme = theme;
},
setValueByKey<T extends keyof AppState>(key: T, value: AppState[T]) {
Object.assign(this.$state, {
[key]: value
})
}
}
})
// app.vue
const appStore = useAppStore();
appStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// 和 cartStore.$id 一样
mutation.storeId // 'cart'
// 只有 mutation.type === 'patch object'的情况下才可用
mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
mutation.event
// 每当状态发生变化时,将整个 state 持久化到本地存储。
localStorage.setItem('cart', JSON.stringify(state))
})
在开发者模式下,mutation中会有一个events对象,控制台可以打印出store的具体变化,key,newValue,oldValue等
但是却无法再生产环境下使用
官方讨论的结果
https://github.com/vuejs/pinia/discussions/1117
所以想要监听store的具体是哪个key发生了变化的需求就无法实现了。
我们知道,watch方法可以监听一整个对象的变化,也可以监听对象的具体属性变化,
const data = reactive({
a: "a",
b: 'b'
});
watch(data, (newVal, oldVal) => { })
watch(() => data.a, (newVal, oldVal) => { })
const appStore = useAppStore();
//使用watch 监听每一个对象
const watchs = (() => {
return Object.keys(appStore.$state).map(key => {
return watch(() => appStore.$state[key], newVal => {
// ....
bus.$emit(`on-${key}-change`, newVal)
}, { immediate: true })
})
});
let watchEffects = watchs();
//当state有动态添加或者删除的属性时,解除监听,并重新执行依赖收集
appStore.$subscribe((mutation, state) => {
if (Object.keys(state).length !== watchEffects.length) {
// 清空watch
watchEffects.forEach(e => e());
// 重新监听对象的每一个属性
watchEffects = watchs()
}
})