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
もちろん、それが要点です)
ストアインスタンスのwatch
メソッドを使用してtime
状態を監視し、そのfetchPositionsAtTime
値が変更されるたびにtime
アクションをディスパッチできます。
store.watch((state) => state.time.time, (val) => {
store.dispatch('position/fetchPositionsAtTime', { time: val })
});
状態を直接見たくない場合は、次のようなゲッターも見ることができます。
store.watch((state, getters) => getters['time/time'], (val) => {
store.dispatch('position/fetchPositionsAtTime', { time: val })
});
Vuex.StoreインスタンスのAPIドキュメントへのリンクは次のとおりです。
次に例を示します。
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>