首页 > 解决方案 > 有没有办法知道什么时候调用vuex store的replaceState函数?

问题描述

vuex-presistedstate在我的项目中使用。在 github 上的源代码中,该插件调用store.replaceState了从存储中水合存储。有没有办法知道商店什么时候补水?

标签: vue.jsvuex

解决方案


vuex-presistedstate插件有一个名为的配置选项rehydrated,允许您传递将在replaceState. 如果您只关心replaceState来自该插件的调用,那么它应该很好地满足您的需求。

我不相信商店本身为何时replaceState被调用提供了一个“钩子”。该方法replaceState在这里实现:

https://github.com/vuejs/vuex/blob/e0126533301febf66072f1865cf9a77778cf2176/src/store.js#L183

正如您从代码中看到的那样,它并没有做太多事情。即使使用注册的订阅者subscribe也不会被调用。但是,您可能会使用watch在状态中的特定属性上注册观察者并使用它来检测状态何时被替换:

https://vuex.vuejs.org/api/#watch

当然,您需要小心地构造事物,以便只有replaceState触发观察者的调用,这可能会变得很繁琐。

另一种选择是修补/覆盖该replaceState方法。用您自己的调用原始方法的方法替换它,为您可能需要的任何额外功能提供一个挂钩点。

我试图在下面的示例中演示以上所有内容:

// Can't use localStorage in an SO snippet...
const fakeStorage = {
  vuex: `{"flag": {}, "number": ${Math.random()}}`
}

const storage = {
  getItem (key) {
    return fakeStorage[key]
  },
  
  setItem (key, value) {
    fakeStorage[key] = value
  },
  
  removeItem (key) {
    delete fakeStorage[key]
  }
}

// Override replaceState with our own version
class StoreOverride extends Vuex.Store {
  replaceState (...args) {
    super.replaceState(...args)
    console.log('replaceState called')
  }
}

const store = new StoreOverride({
  state: {
    flag: {},
    number: 0
  },
  
  plugins: [
    createPersistedState({
      rehydrated () {
        console.log('rehydrated called')
      },
      
      storage
    })
  ]
})

store.subscribe(() => {
  console.log('store.subscribe called (will not happen for replaceState)')
})

store.watch(state => state.flag, () => {
  console.log('store.watch called')
})

console.log('creating Vue instance')

new Vue({
  el: '#app',
  store,
  
  methods: {
    onReplace () {
      // The property 'number' is changed so we can see something happen
      this.$store.replaceState({
        flag: {},
        number: this.$store.state.number + 1
      })
    }
  }
})
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<script>
Vue.config.devtools = false
Vue.config.productionTip = false
</script>
<script src="https://unpkg.com/vuex@3.1.1/dist/vuex.js"></script>
<script src="https://unpkg.com/vuex-persistedstate@2.7.0/dist/vuex-persistedstate.umd.js"></script>

<div id="app">
  <button @click="onReplace">Replace</button>
  <p>{{ $store.state.number }}</p>
</div>


推荐阅读