這個問題是解決基於 vue 和 electron 的開發中使用 vuex 的 dispatch 無效的問題,即解決了 Please, don't use direct commit's, use dispatch instead of this. 問題。
先允許我梳理一下目錄結構,以便閱讀的時候不會一頭霧水,你到底說的這個文件是哪個……
其中 /src/main 是存放主配置文件的,/src/render 下面有 store、router、components 等。components 下面就是很多 .vue 文件,router 下面就是一些路由配置的 js 文件和一些攔截器的 js。
關鍵是 store,store 下面有一個 index.js 的主配置文件 index.js,和一個 modules 文件夾。index.js 里面寫的是(記住這句話,后面會用到):
import Vue from 'vue'
import Vuex from 'vuex'
import { createPersistedState, createSharedMutations } from 'vuex-electron'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules,
plugins: [
createPersistedState(),
createSharedMutations()
],
strict: process.env.NODE_ENV !== 'production'
})
而 modules/ 下面存放各個實體,例如上圖中的 Auth.js 和 Counter.js,並通過 index.js 全部引入。
/** * The file enables `@/store/index.js` to import all vuex modules * in a one-shot manner. There should not be any reason to edit this file. */
const files = require.context('.', false, /\.js$/)
const modules = {}
files.keys().forEach(key => {
if (key === './index.js') return
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})
export default modules
然后來看一個 vuex 的官方樣例:
const state = {
main: 0
}
const mutations = {
DECREMENT_MAIN_COUNTER (state) {
state.main--
},
INCREMENT_MAIN_COUNTER (state) {
state.main++
}
}
const actions = {
someAsyncTask ({ commit }) {
// do something async
commit('INCREMENT_MAIN_COUNTER')
}
}
export default {
state,
mutations,
actions
}
之后很顯然的,我想要在 Vue 的組件調用 INCREMENT_MAIN_COUNTER 對計數器加 1。
this.$store.commit('INCREMENT_MAIN_COUNTER');
// this.$store.commit('INCREMENT_MAIN_COUNTER', payload);
如果是一般的 vue,就 OK 了,但是,我遇到了報錯,說,Please, don't use direct commit's, use dispatch instead of this.
那好吧,沒事,不就是不然用 Commit,非要用 Dispatch 嘛,那我就寫一個 Action,里面直接調用 Mutation,就像這個樣子:
const actions = {
JUST_INCREASE ({ commit }) {
commit('INCREMENT_MAIN_COUNTER')
}
}
然而奇怪的事情是,this.$store.dispatch('JUST_INCREASE') 並不能運行,沒反應,計數器還是 0,不能賦值,就像是這個函數沒有被執行一樣。沒有報錯,沒有任何異常,查也查不出什么問題。

網上的資料似乎也挺少。
折騰了很久,后來發現是 vuex-electron 里面一個插件的鍋。
解決方法有兩個。
方法一:
在 store/index.js 里面,就是上文特別強調了的那個文件,去掉 createSharedMutations 插件。
import Vue from 'vue'
import Vuex from 'vuex'
import { createPersistedState, createSharedMutations } from 'vuex-electron'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules,
plugins: [
createPersistedState(),
createSharedMutations() // 注釋掉這一行
],
strict: process.env.NODE_ENV !== 'production'
})
這是因為 vuex-electron 引入了一個用於多進程間共享 Vuex Store 的狀態的插件。如果沒有多進程交互的需求,完全可以不引入這個插件。
注釋掉以后重啟項目,用 this.$store.commit('XXX') 就可以使用了。
然而,如果需要多進程來處理怎么辦?
方法二:
https://github.com/vue-electron/vuex-electron#installation
看第 3 條:
In case if you enabled
createSharedMutations()plugin you need to create an instance of store in the main process. To do it just add this line into your main process (for examplesrc/main.js):import './path/to/your/store'這種時候就不能用第一種方法來解決問題了。
好在文檔也說了,加上一行導入。
找到/src/main/index.js,在前面加上一句:import '../renderer/store'
之后一切正常,可以使用 Dispatch 來進行操作了。
最后還有一個比較奇怪的問題:
在直接調用state的時候,這樣寫this.$store.state.loginStatus是不行的,會 undefined,必須寫成this.$store.state.Auth.loginStatus,就像是this.$store.state.Counter.main一樣,似乎可以解釋為,不同的模塊不指定名字的話就找不到。
但是,在寫 Dispatch 的時候又不需要指定名字了,直接dispatch('changeLoginStatus')就行了,不然難道不應該是也按照dispatch('Auth/changeLoginStatus')這樣子來寫嘛……



