通過文章的學習,你可以了解以下内容
- 如何進行Vue modules的定義
- 如何調用不同module的内容
- 重構現有未分module的代碼
前言
在前面的章節中,我們都是使用一個store對象,如果不同的業務功能,都需要進行狀态聲明,那這個對象就會變得很大,也不好管理,這時就需要将 store進行子產品管理。
定義
const module1 = {
state: ()=>({}),
mutations: {},
actions: {},
getters: {}
}
const module2 = {
state: ()=>({}),
mutations: {},
actions: {},
getters: {}
}
// 建立多子產品的Store
var store = new Vuex.Store({
modules: {
one: module1,
two: module2
}
})
// 元件中通路
store.state.one // one子產品的狀态通路
store.state.two // two子產品的狀态通路
子產品局部狀态
const module1 = {
state: () => ({
name: ""
}),
mutations: {
modifyName(state, name) {
state.name = name;
}
},
actions: {
modifyName({ state, commit, rootState }, name) {
if (rootState.name == 'test')
commit('modifyName', name);
}
},
getters: {
getName(state,getters,rootState) {
return state.name;
}
}
}
- 對于子產品内部的 mutation 和 getters,接收的第一個參數是子產品的局部狀态對象
- 對于局部狀态通過 context.state 進行暴露,根節點狀态則通過 context.rootState通路
- 對于 getters,則通過第三個參數 rootState 進行根節點的暴露
命名空間
預設情況下,子產品内部的 action、mutation和getter 是注冊在全局命名空間的。如果想讓子產品具有更高的封裝度和複用性,可以指定 namespaced: true 使其成為帶命名子產品
const module1 = {
namespaced: true,
state: () => ({
name: ""
}),
mutations: {
modifyName(state, name) {
state.name = name;
}
},
actions: {
modifyName({ state, commit, rootState }, name) {
if (rootState.name == 'test')
commit('modifyName', name);
}
},
getters: {
getName(state) {
return state.name;
}
},
// 嵌套子產品
modules: {
aOne: { // 繼承父命名空間
state: () => ({
achild: ""
}),
getters: {
getAchild(state) {
return state.achild;
}
}
},
// 嵌套命名空間
aTwo: {
namespaced: true,
state: () => ({
aTwoChild: ""
}),
getters: {
getAtwo(state) {
return state.aTwoChild;
}
}
}
}
}
const store = new Vuex.Store({
a: module1
})
store.state.a // => 通路a子產品的狀态
store.getters.a.getAchild
store.getters.a.aTwo.getAtwo //
在帶命名空間子產品内通路全局内容
全局的 state 和 getter 會 以rootState 和 rootGetters 作為第三個和第四個參數傳入 getter ,同時也會通過 context 對象的屬性傳入action。
如果想在全局命名空間分發action 或送出mutation ,将 { root: true} 作為第三個參數傳給 dispatch 或是 commit
const module1 = {
namespaced: true,
state: () => ({
name: ""
}),
mutations: {
modifyName(state, name) {
state.name = name;
}
},
actions: {
modifyName({ state, dispatch, commit, rootState }, name) {
if (rootState.name == 'test')
commit('modifyName', name); // 子產品局部muation
dispatch('moduleAction');
dispatch('rootAction', null, { root: true }) // 全局 rootAction
commit('rootMutation', null, { root: true }) // 全局mutation
}
},
getters: {
getName(state, getters, rootState, rootGetters) {
return state.name;
}
}
}
當在多子產品中,需要進行調用指定子產品的方法,通過 store.dispatch("namespace/method")的方式進行調用,如果是全局的,則直接調用store.dispatch("method")
實踐
通過以上的了解,接下來我們來定義一個兩個子產品 app 和 user ,來實踐下
- 定義 app.js 和 user.js 定義兩個子產品的内容
- 建立 store 目錄,結構如下
- 在store 目錄下建立modules,建立 user.js 和 app.js, 内容如下
// app.js
const state = {
appId: "",
title: ""
}
const mutations = {
SET_TITLE: (state, title) => {
state.title = title
},
SET_APPID: (state, appId) => {
state.appId = appId
}
}
const actions = {
setTitle({ commit }, title) {
commit('SET_TITLE', title);
},
setAppId({ commit }, appId) {
commit('SET_APPID', appId)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
// user.js
const state = {
id: "",
name: ""
}
const mutations = {
SET_ID: (state, id) => {
state.id = id
},
SET_NAME: (state, name) => {
state.name = appId
}
}
const actions = {
setID({ commit }, id) {
commit('SET_ID', id);
},
setName({ commit }, name) {
commit('SET_NAME', name)
}
}
export default {
namespaced: true,
state,
mutations,
actions
}
- 在 store 目錄下建立 index.js 檔案,内容如下
import Vue from 'vue'
import Vuex from 'vuex';
import app from './modules/app'
import user from './modules/user'
Vue.use(Vuex)
// 建立兩個子產品
const store = new Vuex.Store({
modules: {
app,
user
}
})
export default store
- 導入 store 到 vue 執行個體中
import store from './store'
new Vue({ data: data, render: h => h(App), store }).$mount("#app");
- 擷取store資料
<template>
<div class="hello">
<h1>input text {{ inputValue }}</h1>
<button @click="setAppName">修改appName</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
count: 0,
};
},
methods: {
setAppName() {
this.count++;
// 調用指定子產品下的方法
this.$store.dispatch("app/setTitle", this.count);
},
},
computed: {
// 設定計算屬性
inputValue() {
// 傳回app子產品下的狀态資料
return this.$store.state.app.title;
},
},
};
</script>
總結
命名空間是為了解耦 store的單一狀态,各司其職的劃分子產品,可以提升代碼的擴充性和可維護性