文章目录
一、文章参考
问题描述
工作中,如果将所有的数据放到一个state中,数据量非常大就不便于维护,尤其是项目比较大分模块开发的时候,为了彼此不影响和便于维护,就需要加state通过命名空间隔离,因此大的项目就必须采用Vuex的模块命名。
学习条件
了解Vuex前面的基础 —— state、mutations、actions、getters
二、快速入门 vuex module模块
- 创建 one 和 two 两个 vuex module
one.js
export default {
namespaced: true, // 需要命名空间隔离
state () {
return {
name: 'one'
}
},
getters: {
},
mutations: {
changeName (state) {
state.name = 'one-changeName'
}
},
actions: {
}
}
two.js
export default {
state () {
return {
name: 'two'
}
},
getters: {
},
mutations: {
changeName (state) {
state.name = 'two-changeName'
}
},
actions: {
}
}
- 将one和two两个vuex的模块引入进来
import { createStore } from 'vuex'
import one from './one'
import two from './two'
export default createStore({
state () {
return {
name: 'xxx'
}
},
getters: {
},
mutations: {
changeName (state) {
state.name = 'xxx-changeName'
}
},
actions: {
},
modules: {
one,
two,
}
})
- 工程中引入 vuex
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App)
app.use(router) // 加载路由
app.use(store) // 价值 vuex
app.mount('#app')
- 测试vuex的 module
<template>
<div>store: {{ $store.state.name }}</div>
<div>one.store: {{ $store.state.one.name }}</div>
<div>two.store: {{ $store.state.two.name }}</div>
<div>
<button @click="changeName">改变name 的值</button>
</div>
<div>
<button @click="changeModuleOneName">改变module one 的name 的值</button>
</div>
</template>
<script>
export default {
created() {},
mounted() {},
data() {
return {};
},
methods: {
changeName () {
this.$store.commit('changeName')
},
changeModuleOneName () {
this.$store.commit('one/changeName')
}
},
};
</script>
访问 state 中的数据结果如下:
改变 state 中的数据效果如下:
改变 module one state 中的数据效果如下:
结论:
- 如果使用 modules 定义vuex,则state 是被隔离的,例如:
$store.state.two.name
- 如果module中没有定义
namespaced: true
, 则 mutations 的方法是针对全范围所有定义mutations - 如果定义了
namespaced: true
,则需要添加命名空间
触发,例如this.$store.commit('one/changeName')
三、如何使用 module 拆分巨大的Vuex 对象
简单sample 说明
定义的vuex module要设置namespaced: true,
import state from './countState'
import mutations from './countMutations'
import getters from './countGetters'
import actions from './countActions'
export default {
// 采用了命名空间,默认值为false
namespaced: true,
state,
getters,
actions,
mutations
}
自定义的Vuex module对象要挂载在 modules属性下
import countStore from './count/countIndex'
//创建store仓库暴露出去
export default new Vuex.Store({
modules: {
countModule: countStore
}
})
vuex模块文件管理
- 将一个模块设置为一个文件夹
- 文件夹下包含state、mutations、actions、getters,分别代表各自的数据
- 定义一个moduleIndex.js 文件,作为一个导出文件
state 文件
export default {
count: 0
}
mutations 文件
export default {
// state 是对应命名空间下面的state
// paramObj 是传递过来的参数
addCount: function (state, paramObj) {
state.count = state.count + paramObj.step;
},
minuseCount: function (state, paramObj) {
state.count = state.count - paramObj.step;
}
}
actions 文件
export default {
increment: function (context) {
console.dir(context);
debugger
window.setTimeout(function () {
context.commit({
type: 'addCount',
step: 2
});
}, 1000);
},
// {} 内的参数是 context 上下文中包含的对象
reduce: function ({commit, dispatch, state, rootState, getters, rootGetters}) {
window.setTimeout(function () {
commit({
type: 'minuseCount',
step: 1
});
}, 1000);
}
}
getters 文件
export default {
getDoubleNum: function (state) {
debugger
return state.num * 2;
}
}
countIndex 文件
import state from './countState'
import mutations from './countMutations'
import getters from './countGetters'
import actions from './countActions'
export default {
// 采用了命名空间,默认值为false
namespaced: true,
state,
getters,
actions,
mutations
}
针对模块的 mapState
methods: {
// 添加
addNum: function () {
debugger
this.$store.commit({
type:'countModule/addCount',
step: 1
});
},
// 删除
minuseNum: function () {
this.$store.commit('countModule/minuseCount', {
step: 2
});
},
// 异步调用Action 触发事件
addNumAction: function () {
this.$store.dispatch('countModule/increment');
},
// // 异步调用Action 触发事件
// minuseNumAction: function () {
// this.$store.dispatch('countModule/reduce');
// }
// 与上面等价
...mapActions('countModule',[
'reduce' // this.$store.dispatch('countModule/reduce');
])
},
针对模块的 mapActions
computed: {
myname: function () {
return this.name + ' of hubei';
},
...mapState({
count: function (state) {
console.dir(state);
return state.countModule.count;
}
}),
...mapState('countModule',{
countNew: 'count'
}),
doubleNum: function () {
debugger
return this.$store.state.countModule.count * 2;
}
}
Vue界面关联
<template>
<div>
<div>{{myname}}</div>
<div>count : {{count}}</div>
<div>countNew : {{countNew}}</div>
<div>double count: {{doubleNum}}</div>
<div>
<button @click='addNum'>同步 添加 </button>
</div>
<div>
<button @click='addNumAction'>异步 添加 </button>
</div>
<div>
<button @click="minuseNum">同步减少 </button>
</div>
<div>
<!-- <button @click="minuseNumAction">异步减少 </button> -->
<button @click="reduce">异步减少 </button>
</div>
</div>
</template>
<script>
// mapGetters 和 mapMutations 就是尝试了一下,关于有命名空间,尝试了多种办法,没有结果
import {mapState, mapGetters, mapActions, mapMutations} from 'vuex'
export default {
data: function () {
return {
name: 'countModule/huangbiao'
}
},
mounted: function () {
console.dir(this);
debugger
},
methods: {
// 添加
addNum: function () {
debugger
this.$store.commit({
type:'countModule/addCount',
step: 1
});
},
// 删除
minuseNum: function () {
this.$store.commit('countModule/minuseCount', {
step: 2
});
},
// 异步调用Action 触发事件
addNumAction: function () {
this.$store.dispatch('countModule/increment');
},
// // 异步调用Action 触发事件
// minuseNumAction: function () {
// this.$store.dispatch('countModule/reduce');
// }
// 与上面等价
...mapActions('countModule',[
'reduce' // this.$store.dispatch('countModule/reduce');
])
},
computed: {
myname: function () {
return this.name + ' of hubei';
},
...mapState({
count: function (state) {
console.dir(state);
return state.countModule.count;
}
}),
...mapState('countModule',{
countNew: 'count'
}),
doubleNum: function () {
debugger
return this.$store.state.countModule.count * 2;
}
}
}
</script>
<style>
</style>
三、文件夹的管理
-
目录接口如下图所示:
-
各个模块的js结构如下
-
使用index.js 将各个模块串联起来
import Vue from 'vue'
import Vuex from 'vuex'
import routes from '../router/routes'
const files = require.context('./modules', false, /\.js$/)
console.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
// ƒ webpackContext(req) {
// return __webpack_require__(webpackContextResolve(req));
// }
console.log(files)
// undefined
console.log(JSON.stringify(files))
// ["./location.js","./map.js","./pc-controller.js","./police-manage.js","./road-conf.js","./road-manage.js"]
console.log(JSON.stringify(files.keys()))
let modules = {}
files.keys().forEach(key => {
if (key === './index.js') return
// {default: {…}, __esModule: true}
// default:
// actions: {fetchTaskList: ƒ, fetchRoadList: ƒ}
// mutations: {taskList: ƒ, roadList: ƒ, currentTaskIndexCode: ƒ, currentRoadIndexCode: ƒ, selectedShowRoadsIndexCode: ƒ}
// namespace: "road-manage"
// namespaced: true
// state: {…}
console.log(files(key))
let module = files(key).default
modules[module.namespace] = module
})
Vue.use(Vuex)
export default new Vuex.Store({
state: {},
getters: {},
mutations: {},
actions: {},
modules,
})