当我们在开发大项目时,假设在Vuex中还是没有使用modules,那么我们的state、mutations、actions将会变得十分凌乱和杂乱无章,那么下面我们使用modules,不仅要使代码简洁,还要使得结构更清晰。
我之前写了一篇关于Vuex的基础用法,初学者可以参考,Vuex基础。基础用法只能用于学习新知识,当有了基础之后,我们就需要重构代码。
Vuex结构:
我在store目录下创建了modules、getters.js、index.js文件,而modules中又创建了三个模块。
下面分别在三个模块中写入简单代码:
app.js:
const state = {
count: 5,
device: 'desktop',
}
const mutations = {
SET_COUNT: (state, count) => {
state.count = count
},
}
const actions = {
setCount({
commit }, count) {
commit('SET_COUNT', count)
},
}
export default {
namespaced: true,
state,
mutations,
actions,
}
permission.js:
const state = {
roles: ['admin', 'user'],
}
const mutations = {
getRoutes: (state) => {
return state.roles
},
}
export default {
namespaced: true,
state,
mutations,
}
user.js:
const state = {
token: 'fjwifjwijfshufhehsuhfuehuhuis',
name: 'YaRong',
introduction: '大三学生一枚',
}
const mutations = {
SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction
},
SET_TOKEN: (state, token) => {
state.token = token
},
}
const actions = {
setIntroduction({
commit }, introduction) {
commit('SET_INTRODUCTION', introduction)
},
}
export default {
namespaced: true,
state,
mutations,
actions,
}
注意:namespaced
属性必须设置,设置为true表明每个module有独立的命名空间,即各模块不会相互干扰,类似Vue模块的CSS中的scoped属性。
src/store/getters.js:
const getters = {
name: (state) => state.user.name.toUpperCase(),
count: (state) => {
return state.app.count + '万'
},
length: (state) => state.permission.roles.length,
}
export default getters
注意:留意箭头函数的内容,想要获取哪个模块的state的状态,格式为:state.模块名.变量名
。
下面看关键的index.js文件
src/store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
const modulesFiles = require.context('./modules', true, /\.js$/)
/**
* reduce语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
*/
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') //获取文件名:app,permission,user
const content = modulesFiles(modulePath) //通过路径获取每个文件的内容
modules[moduleName] = content.default //比如app.js文件,modules.app等于export default的内容
return modules
}, {
})
const store = new Vuex.Store({
modules,
getters,
})
export default store
上面我使用了webpack的require.context()
函数,这函数的功能是什么?这样的好处是什么呢?该函数主要用来实现自动化导入模块,在前端工程中,如果遇到从一个文件夹引入很多模块的情况,可以使用这个api,它会遍历文件夹中的指定文件,然后自动导入,使得不需要每次显式的调用import导入模块。我们这里只是使用了三个模块作为示例,假如有上百个文件的,如果不使用这种方法,那么就需要写什么import来导入,这就。。。
在main.js中导入注册:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
render: (h) => h(App),
store,
}).$mount('#app')
在App.vue使用:
<template>
<div id="app">
<h3>{
{
name}}</h3>
<button @click="setToken">修改</button>
<button @click="setIntroduction">修改</button>
</div>
</template>
<script>
import {
mapGetters } from "vuex"
export default {
name: "App",
components: {
},
computed: {
...mapGetters(['name'])
},
methods: {
setToken () {
this.$store.commit('user/SET_TOKEN', '我是修改后的token')
},
setIntroduction () {
setTimeout(() => {
this.$store.dispatch('user/setIntroduction', '我是前端工程师')
}, 2000)
}
}
};
</script>
<style>
</style>
上面展示了getters、mutations、actions是如何调用的。
注意:mutations、actions的调用的第一个参数是需要指明是哪个module的东西。
Vuex是可以正常使用于记录状态。
在复杂的大项目中,我们只需在划分的的module中书写Vuex,这样将结构更加清晰,有利于源码的阅读。