【问题标题】:Can a Vuex module watch another Vuex module?一个 Vuex 模块可以监视另一个 Vuex 模块吗?
【发布时间】:2018-10-01 11:48:36
【问题描述】:

Vuex 模块可以监视其他模块的状态,并因此触发动作吗?

例如,让我们考虑以下情况:

store.js

import time from './store/time' ;
import position from './store/position' ;

const store = new Vuex.Store
(
    {
        modules:
        {
            time,
            position
        }    
    }
) ;

store/time.js

export default
{

    namespaced: true,

    state:
    {
        time: new Date()
    },

    getters:
    {
        time: (aState) => aState.time
    },

    mutations:
    {

        setTime (aState, aTime)
        {
            aState.time = aTime ;
        }

    }

} ;

store/position.js

export default
{

    namespaced: true,

    state:
    {
        positions: {}
    },

    getters:
    {
        positions: aState => aState.positions
    },

    mutations:
    {

        setPositions (aState, aPositionArray)
        {
            aState.positions = aPositionArray ;
        }

    },

    actions:
    {

        fetchPositionsAtTime ({ dispatch, commit, rootGetters }, { time })
        {
            // Fetch positions at given time from the server
            // commit('setPositions', ...)
        }

    }

} ;

理想情况下,我希望位置模块监视时间模块,并在时间状态更改后立即重新获取位置(即触发fetchPositionsAtTime)。

当然,我可以将调度添加到setTime 突变以触发位置模块操作,但我相信反过来(即观看)会更优雅(因为更多模块可能需要时间)。

有什么解决办法吗? (当然不使用Vue Component,这就是重点)

【问题讨论】:

    标签: vue.js vuex vuex-modules


    【解决方案1】:

    您可以使用 store 实例的 watch 方法观察 time 状态,然后在 time 值更改时调度 fetchPositionsAtTime 操作:

    store.watch((state) => state.time.time, (val) => {
      store.dispatch('position/fetchPositionsAtTime', { time: val })
    });
    

    如果您不想直接查看状态,也可以像这样查看 getter:

    store.watch((state, getters) => getters['time/time'], (val) => {
      store.dispatch('position/fetchPositionsAtTime', { time: val })
    });
    

    Here's a link to the api documentation for Vuex.Store instances.


    这是一个例子:

    const time = {
      namespaced: true,
      state: {
        time: new Date()
      },
      getters: {
        time: (aState) => aState.time
      },
      mutations: {
        setTime (aState, aTime) {
          aState.time = aTime ;
        }
      }
    };
    
    const position = {
      namespaced: true,
      state: {
        positions: {}
      },
      getters: {
        positions: aState => aState.positions
      },
      mutations: {
        setPositions (aState, aPositionArray) {
          aState.positions = aPositionArray ;
        }
      },
      actions: {
        fetchPositionsAtTime ({ dispatch, commit, rootGetters }, { time }) {
          let value = rootGetters['position/positions'].value || 0;
          commit('setPositions', { value: ++value });
        }
      }
    };
    
    const store = new Vuex.Store({
      modules: { time, position }    
    });
    
    store.watch((state) => state.time.time, (val) => {
      store.dispatch('position/fetchPositionsAtTime', { time: val })
    });
    
    new Vue({
      el: '#app',
      store,
      methods: {
        setTime() {
          this.$store.commit('time/setTime', new Date());
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
    
    <div id="app">
      time: {{ $store.getters['time/time'] }}
      <br>
      position: {{ $store.getters['position/positions'] }}
      <br>
      <button @click="setTime">Change time</button>
    </div>

    【讨论】:

    • 这确实是一个非常酷的解决方案,谢谢!这也适用于观察吸气剂而不是直接观察状态吗?
    • 谢谢!就我而言,要使用 getter,我必须使用 store.watch(() => store.getters['time/time'], ...) 因为 Typescript 不允许我使用 (state, getters)作为函数参数...
    猜你喜欢
    • 1970-01-01
    • 2017-07-25
    • 2017-05-12
    • 2018-05-02
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 2019-03-07
    • 2021-11-07
    相关资源
    最近更新 更多