一个 Vuex 模块可以监视另一个 Vuex 模块吗?

Posted

技术标签:

【中文标题】一个 Vuex 模块可以监视另一个 Vuex 模块吗?【英文标题】:Can a Vuex module watch another Vuex module? 【发布时间】: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,这就是重点)

【问题讨论】:

【参考方案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)作为函数参数...

以上是关于一个 Vuex 模块可以监视另一个 Vuex 模块吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用来自另一个模块的模块内的 getter 进行 Vuex 状态

在另一个模块操作中获取 vuex 模块状态

如何使用另一个模块中的模块中的getter进行Vuex状态

从 vuex 模块中监听动作/突变

如何从组件访问 Vuex 模块操作

Vuex,命名空间的模块获取器在根获取器中不可用?