Vuex是一个专为Vue.js应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件状态,并在相应的规则保证状态以一种可预测的方式发生变化。
什么情况下会使用到Vuex:比如登录的用户信息,接口的统一访问令牌等,会频繁使用和全站通用的数据,可以寄存在状态管理器中。
一、vuex安装
//输入命令
npm install --save vuex@3
二、store仓库创建
首先在src目录中创建以上文件。
2.1 state.js文件
state.js是用来定义状态管理器的变量,遵循vue中data相同的规则。代码如下:
const state = {
//记录用户信息
userinfo: {},
//记录接口访问令牌
token: ""
};
export default state;
2.2 getters.js文件
getters.js是从store的state中派生出一些状态,对其进行过滤并计数。从字面上就能看出来,是“获取”的意思,所以一般获取状态管理器中变量值和计算,是通过getters来完成的。代码如下:
const getters = {
get_userinfo(state){
return state.userinfo
},
get_token(state){
return state.token
}
};
export default getters;
同时在getters中,也可以对数据进行再加工处理,代码如下:
export default new Vuex.Store({
state: {
menu: [
{"id": 1, "name": "菜单一", "pid": 0},
{"id": 2, "name": "菜单二", "pid": 0},
{"id": 3, "name": "菜单三", "pid": 2},
{"id": 4, "name": "菜单四", "pid": 1}
]
},
getters: {
get_menu(state){
//返回父ID为0的菜单
return state.menu.filter(item => item.pid==0);
}
}
});
2.3 mutationsType.js文件
将mutations中再派生出一个type类型文件,用于记录命令常量值。这些常量后期会在mutations和actions中用到。代码如下:
/**
* 用户信息
* @type {string}
*/
export const CHANGE_USERINFO = "CHANGE_USERINFO";
/**
* 访问令牌
* @type {string}
*/
export const CHANGE_TOKEN = "CHANGE_TOKEN";
2.4 mutations.js文件
更新Vuex的store中的状态的唯一方法是提交mutation。Vuex中的mutations字面意思是裂变,这里理解为对状态管理器state中变量进行“更新”,它是一个修改变量值的事件,第一个参数接收的是state对象。代码如下:
//引入派生出的mutationsType文件
import { CHANGE_USERINFO, CHANGE_TOKEN } from './mutationsType'
const mutations = {
//修改用户信息
[CHANGE_USERINFO](state, param){
state.userinfo = param;
},
//修改访问令牌
[CHANGE_TOKEN](state, param){
state.token = param;
}
};
export default mutations;
2.5 actions.js文件
action类似于mutation,但mutation是同步无异步事件,action是异步事件;而且actions提交的是mutation,而不能直接变更状态;actions中可以包含任意异步操作。代码如下:
//引入派生出的mutationsType文件
import { CHANGE_USERINFO, CHANGE_TOKEN } from './mutationsType'
const actions = {
//修改登录状态信息
changeLoginInfo({commit}, param){
if('undefined'!==typeof param['userinfo']){
commit(CHANGE_USERINFO, param.userinfo);
}
if('undefined'!==typeof param['token']){
commit(CHANGE_TOKEN, param.token);
}
}
};
export default actions;
为什么要使用action呢,个人理解的vuex,是每个担任角色不同,分工也不同而已。
- state是个仓库的功能,如存储在里面的货物(变量);
- getter负责运输的大队长,将货物通过运输工具运到指定位置;同时下面有很多专职司机,每个司机运输货物类别不同,此时则具备货物筛选过滤的功能;如A司机运输是陕西的苹果,B司机运输是山东的苹果,虽然都是苹果,但运输货物种类不同。
- mutation像是一个仓库管理员,等待指令修改货物数量和状态;
- action负责业务层,处理异步请求和任务分发工作。
- mutationsType是派生出的一个指令包,action和mutation通过mutationsType指令表进行下发任务和执行功能。
通过以上分解,希望能帮助刚开始着手使用vuex的同学们,更好理解和使用。
2.6 Modules目录
由于使用单一的状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就会变的非常臃肿。
为了解决这一问题,增加了分割模块(module),每个模块有自己的state、getter、mutation、action。这个很好理解,除总部以外,在全国有34个省级和行政区,每个地方设置一个仓库,每个仓库有自己的仓管、运输队长、业务经理。这样就很好分解了总部的压力,将各地区具体业务进行下放处理。
2.7 index.js文件
此时,我们将所有业务进行汇总,通过index.js将vuex注入到vue中。代码如下:
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import getters from './getters'
import actions from './actions'
import mutations from './mutations'
import mutationsType from './mutationsType'
Vue.use(vuex);
//导入module目录中所有文件
const modulesFiles = require.context('./Modules', true, /\.js$/);
//自动加载Modules目录文件中所有vuex模块
const modules = modulesFiles.keys().reduce((module, modulePath) => {
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1');
const value = modulesFiles(modulePath);
module[moduleName] = value.default;
return module;
}, {});
export default new Vuex.Store({
state,
getters,
actions,
mutations,
modules
});
三、main.js中引入
引入store中的index.js文件,将vuex注入到vue中。代码如下:
import Vue from 'vue'
import App from './App'
import router from './router'
import store from '@/store'
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
});
四、如何使用vuex
4.1 通过store调取
在main.js引入中,已经将引入的store注入到了Vue中,这时我们可以直接通过this.$store来执行相关指令了。
1)this.$store.commit使用,有时公司会绕过业务经理,直接给仓管下达调货指令,则可以使用此方法。代码如下:
import { CHANGE_USERINFO } from '@/store/mutationsType'
export default {
data () {
return {}
},
created(){
//修改用户信息信息
this.$store.commit(CHANGE_USERINFO, {
name: 'tom'
});
}
}
Vuex状态管理器中,userinfo值已被修改,如下图:
2)this.$store.getters使用,获取对应状态信息。代码如下:
export default {
data () {
return {}
},
created(){
console.log(this.$store.getters.get_userinfo);
}
}
控制台输入结果如下图:
3)this.$store.dispatch分发事件,不难理解,dispatch就是给action业务进行任务分发事件。代码如下:
export default {
data () {
return {}
},
created(){
//修改用户信息和访问令牌
this.$store.dispatch('changeLoginInfo', {
userinfo: { name: 'Lily' },
token: 'asfkllk13asdfkl92lka'
})
}
}
此时,用户信息和访问令牌的状态值,已通过action进行指令下发并被修改。如下图:
4.2 通过map调取
1)mapGetters,通过computed完成getters数据导入,代码如下:
import { mapGetters } from 'vuex';
export default {
data () {
return {}
},
computed: {
...mapGetters(['get_token'])
},
created(){
console.log(this.get_token);
}
}
控制台输出如下图:
2)mapActions,通过methods完成action业务功能函数导入,代码如下:
import { mapActions } from 'vuex';
export default {
data () {
return {}
},
methods: {
...mapActions(['changeLoginInfo'])
},
created(){
//修改用户信息
this.changeLoginInfo({
userinfo: { name: "Lily" },
token: "asdfjkljkasdfijiosda21l20adfj"
})
}
}
此时,用户信息和访问令牌的状态值,也通过action进行指令下发并被修改,如下图:
3)mapMutations,通过methods完成mutation事件函数导入,代码如下:
import { mapMutations } from 'vuex';
import { CHANGE_TOKEN } from '@/store/mutationsType'
export default {
data () {
return {}
},
methods: {
...mapMutations([CHANGE_TOKEN])
},
created(){
this[CHANGE_TOKEN]('新token信息');
}
}
Vuex状态管理器中,这时同样已被修改,如下图:
4)mapState,通过computed完成state状态导入。当一个组件需要更多的状态时,将为些状态都声明为计算属性会显的重复和冗余,为了解决这问题,可以使用mapState辅助函数完成生成计算属性,代码如下:
import { mapState } from 'vuex';
export default {
data () {
return {}
},
created(){
console.log('username:', this.username);
},
computed: {
...mapState({
username: state => state.userinfo.name
})
}
}
此时控制台输出如下图:
就此,目前大家项目中常用到的几种方法事件讲完了。有不足之处,欢迎指点。