Есть ли способ узнать, когда вызывается функция replaceState хранилища vuex? - PullRequest
1 голос
/ 14 января 2020

Я использую vuex-presistedstate в своем проекте. В исходном коде на github плагин вызывает store.replaceState, чтобы гидрировать хранилище из хранилища. Есть ли способ узнать, когда в магазине гидраты?

Ответы [ 2 ]

0 голосов
/ 15 января 2020

Вы можете попробовать переписать store.replaceState:

import store from './your/path/to/store'
// ...
store.replaceState = (fn => (...params) => {
  console.log('do something before replaceState called')
  fn.apply(store, params)
  console.log('do something after replaceState called')
})(store.replaceState)

Таким образом, вы можете смотреть не только replaceState, но и любые методы на store экземпляре, если хотите.

0 голосов
/ 15 января 2020

Плагин vuex-presistedstate имеет параметр конфигурации под названием rehydrated, который позволяет вам передавать функцию, которая будет вызываться сразу после replaceState. Если вы заботитесь только о звонках на replaceState из этого плагина, тогда это должно соответствовать вашим потребностям.

Я не верю, что само хранилище обеспечивает «ловушку» для вызова replaceState. Здесь реализован метод replaceState:

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

Как видно из кода, он мало что делает. Даже абоненты, зарегистрированные с помощью subscribe, не звонят. Однако вы могли бы потенциально использовать watch для регистрации наблюдателя в указанном свойстве c в пределах состояния и использовать его для определения, когда состояние заменяется:

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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...