一、什么是Vuex,为什么需要Vuex?
1.1 什么是Vuex?
只要写过vue项目代码的人或多或少都会对Vuex有一定的了解。借用官网上的解释就是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
1.2 为什么需要Vuex?
这个问题其实与1.1是应运而生的。
对于简单的状态管理,其实store模式就足够了。但是组件不允许直接修改属于store示例的state,而应执行action来dispatch事件通知store去改变。这样做的好处就是,我们能够跟踪所有store里面的状态变化(state);这样一来,我们就能够把组件的数据提升成为全局变量/全局数据,我们的组件数据也就自带响应式了。
所以,为了更好的在组件外部管理状态,我们需要借用Vuex。
二、最简单的store状态管理
2.1 载入Vuex实例
图1:最简单的Store
该文件位于store文件夹下面的index.ts文件中,当然这个前提是你已经建好一个vue项目的情况,如果不知道怎么创建,可以参考这篇文章:www.jianshu.com/p/84f998a4c…,帮助你从零开始如何搭建vue项目。
2.2 如何使用
使用就非常简单了。
(1)首先,你得在main.ts里面引入你的store入口文件;main.ts位于/src文件夹的第一层中,一般而言我们主要的入口文件都位于此。其实使用vue-cli创建项目之后,生成的main.ts就已经位于该位置了。如下图:
图2:main.ts文件位置
为什么要引入到该文件呢?因为在main.ts文件中会实例化我们的Vue(你会看到new Vue这样的代码),所以像router这些我们也是在这个文件中统一处理的。
(2)接着,就是在我们的.vue文件里面使用它了(也就是图1中在store里面定义的num)。举例来说,在computed属性里面获取该值:
computed: {
num() {
return this.$store.state.num;
}
}
这个时候,我们在console.log里面打出num,可以奇怪的发现,怎么一直是0,该如何修改num的值呢?答案是:使用commit方法。
图3:修改num值
这个时候再打出num的值,可以发现已经变成1和2了。
这样,我们一个简单的store状态管理就完成了!(*^▽^*)
三、核心框架及各模块分析
在我们深入了解一个技术之前,知道了怎么使用之外,就要开始着眼于“why”这个过程,为什么这样用是可以的,底层的运行机制是怎样的。网上随处都可以找到Vuex的工作流程图,我这里也还是老生常谈的把这个贴出来,这也是官方文档中提供的一个核心点整理:
在第二章节中用到的commit正是如此。
3.1 功能描述
总结:组件接收交互行为,调用dispatch方法触发Actions,如果发现页面状态需要改变,就调用commit方法提交Mutations修改state,通过getters获取到state新值,渲染生成新的页面。
根据上面的图,谈一谈每个模块的基本功能:
- Vue Components:顾名思义就是Vue组件。它负责接收用户的交互行为,执行dispatch方法触发对应action进行回应。
- dispatch:操作行为触发方法,是唯一能执行action的方法。
- actions:操作行为处理模块,提交的是mutation,而不是直接变更状态,它可以包含任意的异步操作。负责处理Vue Components接收到的所有交互行为。
- commit:状态改变提交操作方法。是唯一可以执行mutation的方式。
- mutations:是Vuex修改state的唯一推荐方法。该方法只能进行同步操作,且方法名只能全局唯一。
- state:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。也是我们提取数据的地方:this.$store.state.字段名。
- getters:state对象读取方法,Vue Components通过该方法读取全局state对象,包含在了渲染的过程中。
源代码在Github上:github.com/vuejs/vuex
3.2 Vuex功能使用
首先在src文件夹下面创建Vuex所需的文件,一般为:index.ts(作为入口文件)、actions.ts、getters.ts、interface.d.ts、mutations.ts这些文件取名也正好对应着3.1中的功能。那么每个文件中应该如何写才能让Vuex工作呢?
1. index.ts
作为入口文件,index.ts的地位举足轻重。
import Vue from 'vue';
import Vuex from 'vuex';
import mutations from './mutations';
import actions from './actions';
import getters from './getters';
Vue.use(Vuex); // 告诉Vue我们要开始用Vuex了
export default new Vuex.Store({
state: {
num: 0,
menuItems:[], //如果你想存储你的menu,因为菜单一般而言是不会有太大变动的
},
mutations,
actions,
getters,
},
});
基本上,index.ts就长这个样子了。
2. action.ts
上文也提到了,actions中包含的是一些异步操作,所以看项目中的需要,将异步操作放到该文件来处理。如下我是将获取菜单列表的接口放在action.ts中的(因为菜单列表如果从后台获取之后,一般来说不会经常变化,所以放到store中):
import { ActionContext } from 'vuex';
import axios from 'axios';
export const actions = {
GET_INFO({ commit, rootState }: ActionContext<any, any>, menuParams) {
return axios.get('/get/menuItems', { params: menuParams}).then(({ data }) => { commit('SET_MENU', data.data);
}); }
};
3. mutations.ts
export default {
SET_MENU: (state, info) => {
state.menuItems = info;
},
};
4. getters.ts
该文件内容为空,因为就目前而言,已经基本实现了store的功能了。
export default {};
在需要获取菜单列表的位置,我们可以直接dispatch即可。
mounted() {
this.$store.dispatch('GET_MENU', { id: 11112222 });
}
get menuLists() {
return this.$store.state.menuItems;
}