vue中復(fù)用vuex.store對(duì)象的定義
復(fù)用vuex.store對(duì)象的定義
我有幾個(gè)組件,都需要用到vuex.store,而且這幾個(gè)組件結(jié)構(gòu)極其類(lèi)似,就在想,能不能復(fù)用store的對(duì)象定義?因?yàn)槊總€(gè)組件都定義一遍,繁瑣,且沒(méi)必要。
主要是用到克隆組件。具體代碼如下:
1. 共用的store定義
/src/store/common.js
export default { ? namespaced: true, ? state: { ? ? v: "hello store", // for test ? ? items: [], ? }, ? getters: { ? ? v: (state) => state.v, ? ? items: (state) => { ? ? ? return state.items; ? ? }, ? }, ? mutations: { ? ? // 同步操作 ? ? setV(state, val) { ? ? ? state.v = val; ? ? }, ? ? setItems(state, val) { ? ? ? state.items = val; ? ? }, ? }, ? actions: { ? ? keepItems: ({ commit }, val) => { ? ? ? commit("setItems", val); ? ? }, ? }, };
2. 組件1
/src/store/component1.js
import cloneDeep from "lodash/cloneDeep"; import common from "./common"; const category = cloneDeep(common); export default component1;
3. 組件2
/src/store/component2.js
import cloneDeep from "lodash/cloneDeep"; import common from "./common"; const category = cloneDeep(common); export default component2;
vuex中的store
1. Vuex是什么
在了解Store之前,我們先來(lái)看看Vuex是個(gè)什么東西。Vuex本質(zhì)上就是一個(gè)Vue.js的插件,是用于對(duì)復(fù)雜應(yīng)用進(jìn)行狀態(tài)管理用的,打印Vuex以后輸出:
{ ? ? Store: function Store(){}, ? ? mapActions: function(){}, // 對(duì)應(yīng)Actions的結(jié)果集 ? ? mapGetters: function(){}, // 對(duì)應(yīng)Getters的結(jié)果集 ? ? mapMutations: function(){}, // 對(duì)應(yīng)Mutations的結(jié)果集 ? ? mapState: function(){}, // 對(duì)應(yīng)State的結(jié)果集 ? ? install: function install(){}, ? ? installed: true ? }
Vuex和單純的全局對(duì)象有以下兩點(diǎn)不同:
- Vuex的狀態(tài)存儲(chǔ)是響應(yīng)式的。當(dāng)Vue 組件從 Store 中讀取狀態(tài)的時(shí)候,若 Store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)相應(yīng)地得到高效更新。
- 不能直接改變 Store 中的狀態(tài)。改變Store 中的狀態(tài)的唯一途徑就是顯式地提交 mutation。
2. Store
每一個(gè)Vuex應(yīng)用的核心就是Store(倉(cāng)庫(kù)),我們可以說(shuō)Store是一個(gè)容器,Store里面的狀態(tài)與單純的全局變量是不一樣的,無(wú)法直接改變Store中的狀態(tài)。想要改變Store中的狀態(tài),只有一個(gè)辦法,顯式地提交mutation。
3. 一個(gè)完整的Store結(jié)構(gòu)
const store = new Vuex.Store({ ? state: { ? ? // 存放狀態(tài) ? }, ? getters: { ? ? // state的計(jì)算屬性 ? }, ? mutations: { ? ? // 更改state中狀態(tài)的邏輯,同步操作 ? }, ? actions: { ? ? // 提交mutation,異步操作 ? }, ? // 如果將store分成一個(gè)個(gè)的模塊的話,則需要用到modules。 ? ?//然后在每一個(gè)module中寫(xiě)state, getters, mutations, actions等。 ? modules: { ? ? a: moduleA, ? ? b: moduleB, ? ? // ... ? } });
4. 狀態(tài)管理的幾個(gè)核心概念
1. state
state是狀態(tài)數(shù)據(jù),可以通過(guò)this.$store.state來(lái)直接獲取狀態(tài),也可以利用vuex提供的mapState輔助函數(shù)將state映射到計(jì)算屬性(computed)中去。用data接收的值不能及時(shí)響應(yīng)更新,用computed就可以:
export default { ? data () { ? ? return { ? ? ? dataCount: this.$store.state.count //用data接收 ? ? } ? }, ? computed:{ ? ? count(){ ? ? ? return this.$store.state.count //用computed接收 ? ? } ? } }
mapState 輔助函數(shù):
mapState是state的語(yǔ)法糖,當(dāng)一個(gè)組件需要獲取多個(gè)狀態(tài)時(shí)候,將這些狀態(tài)都聲明為計(jì)算屬性會(huì)有些重復(fù)和冗余。為了解決這個(gè)問(wèn)題,我們可以使用 mapState 輔助函數(shù)幫助我們生成計(jì)算屬性,讓你少按幾次鍵:
// 在單獨(dú)構(gòu)建的版本中輔助函數(shù)為 Vuex.mapState import { mapState } from 'vuex' ? export default { ? // ... ? computed: mapState({ ? ? // 箭頭函數(shù)可使代碼更簡(jiǎn)練 ? ? count: state => state.count, ? ? ? // 傳字符串參數(shù) 'count' 等同于 `state => state.count` ? ? countAlias: 'count', ? ? ? // 為了能夠使用 `this` 獲取局部狀態(tài),必須使用常規(guī)函數(shù) ? ? countPlusLocalState (state) { ? ? ? return state.count + this.localCount ? ? } ? }) }
當(dāng)映射的計(jì)算屬性的名稱(chēng)與 state 的子節(jié)點(diǎn)名稱(chēng)相同時(shí),我們也可以給 mapState 傳一個(gè)字符串?dāng)?shù)組。
computed: mapState([ ? // 映射 this.count 為 store.state.count ? 'count' ])
2. getter
getters本質(zhì)上是用來(lái)對(duì)狀態(tài)進(jìn)行加工處理。Getters與State的關(guān)系,就像Vue.js的computed與data的關(guān)系。getter 的返回值會(huì)根據(jù)它的依賴(lài)被緩存起來(lái),且只有當(dāng)它的依賴(lài)值發(fā)生了改變才會(huì)被重新計(jì)算??梢酝ㄟ^(guò)this.$store.getters.valueName對(duì)派生出來(lái)的狀態(tài)進(jìn)行訪問(wèn)?;蛘咧苯邮褂幂o助函數(shù)mapGetters將其映射到本地計(jì)算屬性中去。
mapGetters 輔助函數(shù):
mapGetters 輔助函數(shù)僅僅是將 store 中的 getter 映射到局部計(jì)算屬性:
import { mapGetters } from 'vuex' export default { ? // ... ? computed: { ? // 使用對(duì)象展開(kāi)運(yùn)算符將 getter 混入 computed 對(duì)象中 ? ? ...mapGetters([ ? ? ? 'doneTodosCount', ? ? ? 'anotherGetter', ? ? ? // ... ? ? ]) ? } }
mapGetters實(shí)際上是一個(gè)方法Vuex對(duì)象上的一個(gè)方法,這從本文開(kāi)頭打印的那個(gè)Vuex對(duì)象的內(nèi)容可以看出來(lái)。…這個(gè)符號(hào)是ES2015的一個(gè)新的語(yǔ)法糖,即將mapGetters處理后的內(nèi)容展開(kāi)后填入。
如果你想將一個(gè) getter 屬性另取一個(gè)名字,使用對(duì)象形式:
mapGetters({ ? // 映射 `this.doneCount` 為 `store.getters.doneTodosCount` ? doneCount: 'doneTodosCount' })
3. mutation
mutations的中文意思是“變化”,利用它可以更改狀態(tài)。事實(shí)上,更改 Vuex 的 store 中的狀態(tài)的唯一方法就是提交 (commit)mutation。不過(guò),mutation觸發(fā)狀態(tài)改變的方式有一點(diǎn)特別,所謂commit一個(gè)mutation,實(shí)際是像觸發(fā)一個(gè)事件一樣,傳入一個(gè)mutation的類(lèi)型以及攜帶一些數(shù)據(jù)(稱(chēng)作payload,載荷)。
mutations: { ? //放置mutations方法 ?? ?increment(state, payload) { ?? ??? ?//在這里改變state中的數(shù)據(jù) ?? ??? ?state.count = payload.number; ?? ?} },
那commit一個(gè)mutation在代碼層面怎么表示呢?
this.$store.commit('increment', { ? amount: 10 }) //或者這樣 this.$store.commit({ ? type: 'increment', ? amount: 10 })
除了這種使用 this.$store.commit('xxx') 提交 mutation的方式之外,還有一種方式,即使用 mapMutations 輔助函數(shù)將組件中的 methods 映射為 this.$store.commit。例如:
import { mapMutations } from 'vuex' ? export default { ? // ... ? methods: { ? ? ...mapMutations([ ? ? ? 'increment', // 將 `this.increment()` 映射為 `this.$store.commit('increment')` ? ? ? ? // `mapMutations` 也支持載荷: ? ? ? 'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)` ? ? ]), ? ? ...mapMutations({ ? ? ? add: 'increment' // 將 `this.add()` 映射為 `this.$store.commit('increment')` ? ? }) ? } }
經(jīng)過(guò)這樣的映射之后,就可以通過(guò)調(diào)用方法的方式來(lái)觸發(fā)其對(duì)應(yīng)的(所映射到的)mutation commit了,比如,上例中調(diào)用add()方法,就相當(dāng)于執(zhí)行了this.$store.commit('increment')了。
考慮到觸發(fā)的mutation的type必須與mutations里聲明的mutation名稱(chēng)一致,比較好的方式是把這些mutation都集中到一個(gè)文件(如mutation-types)中以常量的形式定義,在其它地方再將這個(gè)文件引入,便于管理。而且這樣做還有一個(gè)好處,就是整個(gè)應(yīng)用中一共有哪些mutation type可以一目了然。就像下面這樣:
// mutation-types.js export const SOME_MUTATION = 'SOME_MUTATION' ? // store.js import Vuex from 'vuex' import { SOME_MUTATION } from './mutation-types' ? const store = new Vuex.Store({ ? state: { ... }, ? mutations: { ? ? // 我們可以使用 ES2015 風(fēng)格的計(jì)算屬性命名功能來(lái)使用一個(gè)常量作為函數(shù)名 ? ? [SOME_MUTATION] (state) { ? ? ? // mutate state ? ? } ? } })
4. action
action可以提交mutation,在action中可以執(zhí)行store.commit,而且action中可以有任何的異步操作:
const store = new Vuex.Store({ ? state: { ? ? count: 0 ? }, ? mutations: { ? ? increment (state) { ? ? ? state.count++ ? ? } ? }, ? actions: { ? ? increment (context) { ? ? ? context.commit('increment') ? ? } ? } })
或者用ES2015的參數(shù)解構(gòu),可以簡(jiǎn)寫(xiě)成:
actions: { ? ? increment ({commit}) { ? ? ? ?? ?commit('increment') ? ? } }
和mutation類(lèi)似,我們像上面這樣生命action的處理函數(shù)。它接收的第一個(gè)參數(shù)是一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象,因此你可以調(diào)用 context.commit 提交一個(gè) mutation,或者通過(guò) context.state 和 context.getters 來(lái)獲取 state 和 getters。
不過(guò),mutation處理函數(shù)中所做的事情是改變state,而action處理函數(shù)中所做的事情則是commit mutation。
怎么觸發(fā)action呢?按照Vuex的叫法,這叫分發(fā)(dispatch),我們反正知道它實(shí)際上是觸發(fā)的意思就行了。具體的觸發(fā)方法是this.$store.dispatch(actionType, payload)。所傳的兩個(gè)參數(shù)一個(gè)是要觸發(fā)的action的類(lèi)型,一個(gè)是所攜帶的數(shù)據(jù)(payload),類(lèi)似于上文所講的commit mutation時(shí)所傳的那兩個(gè)參數(shù)。具體如下:
// 以載荷形式分發(fā) this.$store.dispatch('incrementAsync', { ? amount: 10 })
或
// 以對(duì)象形式分發(fā) this.$store.dispatch({ ? type: 'incrementAsync', ? amount: 10 })
還有一種方法是使用 mapActions 輔助函數(shù)將組件的 methods 映射為 this.$store.dispatch 調(diào)用。如下:
import { mapActions } from 'vuex' ? export default { ? // ... ? methods: { ? ? ...mapActions([ ? ? ? 'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')` ? ? ? ? // `mapActions` 也支持載荷: ? ? ? 'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.dispatch('incrementBy', amount)` ? ? ]), ? ? ...mapActions({ ? ? ? add: 'increment' // 將 `this.add()` 映射為 `this.$store.dispatch('increment')` ? ? }) ? } }
另外,還需要知道, this.$store.dispatch 可以處理被觸發(fā)的 action 的處理函數(shù)返回的 Promise,并且 this.$store.dispatch 仍舊返回 Promise。
再來(lái)看一些組合性的異步操作:
actions: { ? actionA ({ commit }) { ? ? return new Promise((resolve, reject) => { ? ? ? setTimeout(() => { ? ? ? ? commit('someMutation') ? ? ? ? resolve() ? ? ? }, 1000) ? ? }) ? } }
現(xiàn)在你可以:
$this.store.dispatch('actionA').then(() => { ? // ... })
在另外一個(gè) action 中也可以:
actions: { ? // ... ? actionB ({ dispatch, commit }) { ? ? return dispatch('actionA').then(() => { ? ? ? commit('someOtherMutation') ? ? }) ? } }
最后,如果我們利用 async / await 這個(gè) JavaScript 即將到來(lái)的新特性,我們可以像這樣組合 action:
// 假設(shè) getData() 和 getOtherData() 返回的是 Promise actions: { ? async actionA ({ commit }) { ? ? commit('gotData', await getData()) ? }, ? async actionB ({ dispatch, commit }) { ? ? await dispatch('actionA') // 等待 actionA 完成 ? ? commit('gotOtherData', await getOtherData()) ? } }
接著來(lái)看一個(gè)更加實(shí)際的購(gòu)物車(chē)示例,涉及到調(diào)用異步 API 和分發(fā)多重 mutation:
actions: { ? checkout ({ commit, state }, products) { ? ? // 把當(dāng)前購(gòu)物車(chē)的物品備份起來(lái) ? ? const savedCartItems = [...state.cart.added] ? ? // 發(fā)出結(jié)賬請(qǐng)求,然后樂(lè)觀地清空購(gòu)物車(chē) ? ? commit(types.CHECKOUT_REQUEST) ? ? // 購(gòu)物 API 接受一個(gè)成功回調(diào)和一個(gè)失敗回調(diào) ? ? shop.buyProducts( ? ? ? products, ? ? ? // 成功操作 ? ? ? () => commit(types.CHECKOUT_SUCCESS), ? ? ? // 失敗操作 ? ? ? () => commit(types.CHECKOUT_FAILURE, savedCartItems) ? ? ) ? } }
5. module
module是對(duì)于store的一種切割。由于Vuex使用的是單一狀態(tài)樹(shù),這樣整個(gè)應(yīng)用的所有狀態(tài)都會(huì)集中到一個(gè)比較大的對(duì)象上面,那么,當(dāng)應(yīng)用變得非常復(fù)雜時(shí),store 對(duì)象就很可能變得相當(dāng)臃腫!它解決了當(dāng)state中很臃腫的時(shí)候,module可以將store分割成模塊,每個(gè)模塊中擁有自己的state、mutation、action和getter。就像下面這樣:
const moduleA = { ? state: { ... }, ? mutations: { ... }, ? actions: { ... }, ? getters: { ... } } ? const moduleB = { ? state: { ... }, ? mutations: { ... }, ? actions: { ... } } ? const store = new Vuex.Store({ ? modules: { ? ? a: moduleA, ? ? b: moduleB ? } }) ? store.state.a // -> moduleA 的狀態(tài) store.state.b // -> moduleB 的狀態(tài)
模塊的局部狀態(tài)
對(duì)于每個(gè)模塊內(nèi)部的 mutation 和 getter,接收的第一個(gè)參數(shù)就是模塊的局部狀態(tài)對(duì)象。
const moduleA = { ? state: { count: 0 }, ? mutations: { ? ? increment (state) { ? ? ? // 這里的 `state` 對(duì)象是模塊的局部狀態(tài) ? ? ? state.count++ ? ? } ? }, ? ? getters: { ? ? doubleCount (state) { ? ? ? return state.count * 2 ? ? } ? } }
同樣,對(duì)于模塊內(nèi)部的 action,局部狀態(tài)通過(guò) context.state 暴露出來(lái),根節(jié)點(diǎn)狀態(tài)則為 context.rootState:
const moduleA = { ? // ... ? actions: { ? ? incrementIfOddOnRootSum ({ state, commit, rootState }) { ? ? ? if ((state.count + rootState.count) % 2 === 1) { ? ? ? ? commit('increment') ? ? ? } ? ? } ? } }
對(duì)于模塊內(nèi)部的 getter,根節(jié)點(diǎn)狀態(tài)會(huì)作為第三個(gè)參數(shù)暴露出來(lái):
const moduleA = { ? // ... ? getters: { ? ? sumWithRootCount (state, getters, rootState) { ? ? ? return state.count + rootState.count ? ? } ? } }
命名空間
默認(rèn)情況下,模塊內(nèi)部的 action、mutation 和 getter 是注冊(cè)在全局命名空間的——這樣使得多個(gè)模塊能夠?qū)ν?mutation 或 action 作出響應(yīng)。
如果希望你的模塊具有更高的封裝度和復(fù)用性,你可以通過(guò)添加 namespaced: true 的方式使其成為命名空間模塊。當(dāng)模塊被注冊(cè)后,它的所有 getter、action 及 mutation 都會(huì)自動(dòng)根據(jù)模塊注冊(cè)的路徑調(diào)整命名。
例如:
const store = new Vuex.Store({ ? modules: { ? ? account: { ? ? ? namespaced: true, ? ? ? ? // 模塊內(nèi)容(module assets) ? ? ? state: { ... }, // 模塊內(nèi)的狀態(tài)已經(jīng)是嵌套的了,使用 `namespaced` 屬性不會(huì)對(duì)其產(chǎn)生影響 ? ? ? getters: { ? ? ? ? isAdmin () { ... } // -> getters['account/isAdmin'] ? ? ? }, ? ? ? actions: { ? ? ? ? login () { ... } // -> dispatch('account/login') ? ? ? }, ? ? ? mutations: { ? ? ? ? login () { ... } // -> commit('account/login') ? ? ? }, ? ? ? ? // 嵌套模塊 ? ? ? modules: { ? ? ? ? // 繼承父模塊的命名空間 ? ? ? ? myPage: { ? ? ? ? ? state: { ... }, ? ? ? ? ? getters: { ? ? ? ? ? ? profile () { ... } // -> getters['account/profile'] ? ? ? ? ? } ? ? ? ? }, ? ? ? ? ? // 進(jìn)一步嵌套命名空間 ? ? ? ? posts: { ? ? ? ? ? namespaced: true, ? ? ? ? ? ? state: { ... }, ? ? ? ? ? getters: { ? ? ? ? ? ? popular () { ... } // -> getters['account/posts/popular'] ? ? ? ? ? } ? ? ? ? } ? ? ? } ? ? } ? } })
啟用了命名空間的 getter 和 action 會(huì)收到局部化的 getter,dispatch 和 commit。
在命名空間模塊內(nèi)訪問(wèn)全局內(nèi)容(Global Assets)
如果你希望使用全局 state 和 getter,rootState 和 rootGetter 會(huì)作為第三和第四參數(shù)傳入 getter,也會(huì)通過(guò) context 對(duì)象的屬性傳入 action。
若需要在全局命名空間內(nèi)分發(fā) action 或提交 mutation,將 { root: true } 作為第三參數(shù)傳給 dispatch 或 commit即可。
modules: { ? foo: { ? ? namespaced: true, ? ? ? getters: { ? ? ? // 在這個(gè)模塊的 getter 中,`getters` 被局部化了 ? ? ? // 你可以使用 getter 的第四個(gè)參數(shù)來(lái)調(diào)用 `rootGetters` ? ? ? someGetter (state, getters, rootState, rootGetters) { ? ? ? ? getters.someOtherGetter // -> 'foo/someOtherGetter' ? ? ? ? rootGetters.someOtherGetter // -> 'someOtherGetter' ? ? ? }, ? ? ? someOtherGetter: state => { ... } ? ? }, ? ? ? actions: { ? ? ? // 在這個(gè)模塊中, dispatch 和 commit 也被局部化了 ? ? ? // 他們可以接受 `root` 屬性以訪問(wèn)根 dispatch 或 commit ? ? ? someAction ({ dispatch, commit, getters, rootGetters }) { ? ? ? ? getters.someGetter // -> 'foo/someGetter' ? ? ? ? rootGetters.someGetter // -> 'someGetter' ? ? ? ? ? dispatch('someOtherAction') // -> 'foo/someOtherAction' ? ? ? ? dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction' ? ? ? ? ? commit('someMutation') // -> 'foo/someMutation' ? ? ? ? commit('someMutation', null, { root: true }) // -> 'someMutation' ? ? ? }, ? ? ? someOtherAction (ctx, payload) { ... } ? ? } ? } }
帶命名空間的綁定函數(shù)
當(dāng)使用 mapState, mapGetters, mapActions 和 mapMutations 這些函數(shù)來(lái)綁定命名空間模塊時(shí),寫(xiě)起來(lái)可能比較繁瑣:
computed: { ? ...mapState({ ? ? a: state => state.some.nested.module.a, ? ? b: state => state.some.nested.module.b ? }) }, methods: { ? ...mapActions([ ? ? 'some/nested/module/foo', ? ? 'some/nested/module/bar' ? ]) }
對(duì)于這種情況,你可以將模塊的空間名稱(chēng)字符串作為第一個(gè)參數(shù)傳遞給上述函數(shù),這樣所有綁定都會(huì)自動(dòng)將該模塊作為上下文。于是上面的例子可以簡(jiǎn)化為:
computed: { ? ...mapState('some/nested/module', { ? ? a: state => state.a, ? ? b: state => state.b ? }) }, methods: { ? ...mapActions('some/nested/module', [ ? ? 'foo', ? ? 'bar' ? ]) }
而且,你可以通過(guò)使用 createNamespacedHelpers 創(chuàng)建基于某個(gè)命名空間輔助函數(shù)。它返回一個(gè)對(duì)象,對(duì)象里有新的綁定在給定命名空間值上的組件綁定輔助函數(shù):
import { createNamespacedHelpers } from 'vuex' ? const { mapState, mapActions } = createNamespacedHelpers('some/nested/module') ? export default { ? computed: { ? ? // 在 `some/nested/module` 中查找 ? ? ...mapState({ ? ? ? a: state => state.a, ? ? ? b: state => state.b ? ? }) ? }, ? methods: { ? ? // 在 `some/nested/module` 中查找 ? ? ...mapActions([ ? ? ? 'foo', ? ? ? 'bar' ? ? ]) ? } }
給插件開(kāi)發(fā)者的注意事項(xiàng)
如果你開(kāi)發(fā)的插件(Plugin)提供了模塊并允許用戶(hù)將其添加到 Vuex store,可能需要考慮模塊的空間名稱(chēng)問(wèn)題。對(duì)于這種情況,你可以通過(guò)插件的參數(shù)對(duì)象來(lái)允許用戶(hù)指定空間名稱(chēng):
// 通過(guò)插件的參數(shù)對(duì)象得到空間名稱(chēng) // 然后返回 Vuex 插件函數(shù) export function createPlugin (options = {}) { ? return function (store) { ? ? // 把空間名字添加到插件模塊的類(lèi)型(type)中去 ? ? const namespace = options.namespace || '' ? ? store.dispatch(namespace + 'pluginAction') ? } }
模塊動(dòng)態(tài)注冊(cè)
在 store 創(chuàng)建之后,你可以使用 store.registerModule 方法注冊(cè)模塊:
// 注冊(cè)模塊 `myModule` store.registerModule('myModule', { ? // ... }) // 注冊(cè)嵌套模塊 `nested/myModule` store.registerModule(['nested', 'myModule'], { ? // ... })
之后就可以通過(guò) store.state.myModule 和 store.state.nested.myModule 訪問(wèn)模塊的狀態(tài)。
模塊動(dòng)態(tài)注冊(cè)功能使得其他 Vue 插件可以通過(guò)在 store 中附加新模塊的方式來(lái)使用 Vuex 管理狀態(tài)。例如,vuex-router-sync 插件就是通過(guò)動(dòng)態(tài)注冊(cè)模塊將 vue-router 和 vuex 結(jié)合在一起,實(shí)現(xiàn)應(yīng)用的路由狀態(tài)管理。
你也可以使用 store.unregisterModule(moduleName) 來(lái)動(dòng)態(tài)卸載模塊。注意,你不能使用此方法卸載靜態(tài)模塊(即創(chuàng)建 store 時(shí)聲明的模塊)。
模塊重用
有時(shí)我們可能需要?jiǎng)?chuàng)建一個(gè)模塊的多個(gè)實(shí)例,例如:
(1)創(chuàng)建多個(gè) store,他們公用同一個(gè)模塊
(2)在一個(gè) store 中多次注冊(cè)同一個(gè)模塊
如果我們使用一個(gè)純對(duì)象來(lái)聲明模塊的狀態(tài),那么這個(gè)狀態(tài)對(duì)象會(huì)通過(guò)引用被共享,導(dǎo)致?tīng)顟B(tài)對(duì)象被修改時(shí) store 或模塊間數(shù)據(jù)互相污染的問(wèn)題。
實(shí)際上這和 Vue 組件內(nèi)的 data 是同樣的問(wèn)題。因此解決辦法也是相同的——使用一個(gè)函數(shù)來(lái)聲明模塊狀態(tài)(僅 2.3.0+ 支持):
const MyReusableModule = { ? state () { ? ? return { ? ? ? foo: 'bar' ? ? } ? }, ? // mutation, action 和 getter 等等... }
5. store與$store的區(qū)別
$store 是掛載在 Vue 實(shí)例上的(即Vue.prototype),組件也是一個(gè)Vue實(shí)例,在組件中可使用 this 訪問(wèn)原型上的屬性。template 中可直接通過(guò) {{ $store.state.userName }} 訪問(wèn),等價(jià)于 script 中的 this.$store.state.userName。
至于 {{ store.state.userName }},script 中的 data 需聲明過(guò) store 才可訪問(wèn)。
總之,有以下要注意的:
(1)在功能上:
state
保存的是數(shù)據(jù)getters
是對(duì)state進(jìn)行二次加工action
的處理函數(shù)的功能最終是commit mutationmutation
處理函數(shù)的功能最終是改變state
(2)在流程上:
vue component—-dispatch—->actions—-commit—->mutations—-mutate—->state—-render—->vue component。從而形成閉環(huán)。
(3)輔助方法的映射上:
mapGetters、mapState 都是用在computed聲明里面;
mapActions、mapMutations則都是用在methods聲明里面。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解vue實(shí)現(xiàn)坐標(biāo)拾取器功能示例
這篇文章主要介紹了詳解vue實(shí)現(xiàn)坐標(biāo)拾取器功能示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Vue實(shí)現(xiàn)商品詳情頁(yè)的評(píng)價(jià)列表功能
這篇文章主要介紹了Vue實(shí)現(xiàn)商品詳情頁(yè)的評(píng)價(jià)列表功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09淺談vue.js導(dǎo)入css庫(kù)(elementUi)的方法
下面小編就為大家分享一篇淺談vue.js導(dǎo)入css庫(kù)(elementUi)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03vue 使用插槽分發(fā)內(nèi)容操作示例【單個(gè)插槽、具名插槽、作用域插槽】
這篇文章主要介紹了vue 使用插槽分發(fā)內(nèi)容操作,結(jié)合實(shí)例形式總結(jié)分析了vue.js使用單個(gè)插槽、具名插槽、作用域插槽相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下2020-03-03Ant Design Vue全局對(duì)話確認(rèn)框(confirm)的回調(diào)不觸發(fā)
這篇文章主要介紹了Ant Design Vue全局對(duì)話確認(rèn)框(confirm)的回調(diào)不觸發(fā)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07Vue cli+mui 區(qū)域滾動(dòng)的實(shí)例代碼
下面小編就為大家分享一篇Vue cli+mui 區(qū)域滾動(dòng)的實(shí)例代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01詳解Vue-cli來(lái)構(gòu)建Vue項(xiàng)目的步驟
這篇文章主要為大家介紹了Vue-cli來(lái)構(gòu)建Vue項(xiàng)目的步驟,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12VUE 實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板的兩種方法
這篇文章主要介紹了VUE 實(shí)現(xiàn)復(fù)制內(nèi)容到剪貼板功能,本文通過(guò)兩種方法,給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-04-04