一、vuex是什么
vuex是一个专门为vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件状态,并以相应规则保证状态以一种可观测的方式发生变化。可以理解为:将多个共享的变量全部存储在一个对象里面,然后将这个对象放在顶层的vuex实例中,让其他组件可以共享这个对象里的变量,它最大的特点就是响应式。
通俗来说:Vuex其实就是一个状态管理工具,所谓的状态,就是数据,通过这个工具进行管理某些数据。当多个组件都需要同一个数据时,可以将这个数据交给Vuex进行统一的管理,组件可以直接引用这个数据,避免了组件间繁琐的层层传递的情况。
二、什么情况下我们应该使用vuex
当你无法很好进行数据管理的时候,你才需要用Vuex。一般情况下,我们会在vuex中存放一些需要在多个界面中进行共享的信息。比如用户的登录状态、用户头像、名称、商品的收藏、购物车中的物品等,这些状态信息,我们可以放在同一的地方,对它进行保存和管理。
三、vuex核心
Vuex有五大核心,state,getter,mutation,action,module。state用来存放要被管理的数据,getter相当于computed计算属性,mutation中用来定义要修改state中数据的方法,action中用来定义异步的一些方法,module可以将多个store分成一个一个的模块。
State | 共享状态(存放全局变量) |
Getter | 从 store 中的 state 中派生出一些状态(变量),即从state中获取状态(变量) |
Mutation | 更改 Vuex 的 store 中的状态的唯一方法,通过提交mutation修改状态,同步操作 |
Action | 类似于mutation,不同的是,action不能直接修改state的状态,需要通过提交mutation修改state状态,支持异步 |
Module | 模块,为了方便状态的管理,将store拆分为多个子模块(modules),每个子模块拥有完整的state、getter、mutation、action |
四、vuex具体用法
1、安装
两种方法:
npm install vuex --save
yarn add vuex
(1)在vue项目中使用Vuex时,需要先安装Vuex插件,并且注册,一般情况下都会在,在src下新创建一个store文件夹,下边有一个index.vue,在这个文件中创建store容器实例。
// 1. 安装插件
npm install vuex --save
// 2. 注册插件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
(2)创建vuex实例,在vuex上提供了一个Store()方法,用来创建实例,将其命名为store,意为仓库的意思。在Vuex.Store()中传一个配置对象,配置对象中包括上述的五大核心,如果用不到,也可以不做配置。
const store = new Vuex.Store({
state: {num: 2}, // 存放数据
getters: {}, // 计算属性
mutations: {}, // 修改state中数据的一些方法
actions: {}, // 异步方法
modules: {} // store模块
})
export default store
在入口文件main.js中引入store
import store from './store';
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: { App }
})
2、添加文件
项目完整目录如下:
3、每个文件具体配置
(1)modules
modules里面添加了js文件,命名随意,建议按模板命名,每个模板仅存储该模块的状态。
实例;
假设里面创建了一个form.js和user.js两个文件
form.js
const state = {
count: 0 // 数量
};
const mutations = {
SET_COUNT: (state, data) => {
state.count++;
}
};
const actions = {};
export default {
state,
mutations,
actions
};
user.js
const state = {
name: 0, // 姓名
age: 0, // 年龄
};
const mutations = {
SET_NAME: (state, data) => {
state.name = data;
},
SET_AGE:(state, data) => {
state.age = data;
};
const actions = {};
export default {
state,
mutations,
actions
};
(2)getters.js
所有使用的状态在这里都要列出来
const getters = {
count: state => state.form.count,
name: state => state.user.name,
age: state => state.user.age
}
export default getters
(3)index.js
modules中创建的文件在index.js中药引入一下
import Vue from 'vue'
import Vuex from 'vuex'
import form from './modules/form'
import user from './modules/user'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
form,
user
},
getters
})
export default store
四、使用
在页面中使用:在使用vuex中的数据之前,先使用import导入写好的store。组件中在插值表达式中使用$store.state.num获取store中num的数据(此处的num值为上面创建vuex实例时设置的值)
<template>
<div>
<h2>{{ $store.state.num }}</h2>
</div>
</template>
新建store的js,引入vue和vuex
在实例中注册store
五、store中变量的定义、管理、派生(getter)
1、state — 状态
在store实例中注册state并在state中定义变量text,也可以给一个初始值;在组件中使用$store.state.text使用定义的变量
2、mutation — 更改 store 中的状态的唯一方法
vuex中规定只能通过提交mutation的方式去更改store中的状态,包括action中的操作,也是通过提交mutation去修改,且mutation中不能包含异步操作
说明:在mutations里声明了两个方法,一个是不带参数更新text,一个是带参数更新text,在示例文件的methods里,
通过this.$store.commit('方法名', ‘传参’) 调用,从而达到修改store的状态
3、action — 异步更改状态
action 可支持异步修改state的状态,而修改state的唯一方法是通过mutation,那么想要在action里面修改state,则需要提交一个mutation,由mutation去做修改
说明:<1>、在actions里声明了两个异步方法,一个是不带参数更新text,一个是带参数更新text,在示例文件的methods里,
通过this.$store.dispatch 调用actions的方法,在actions里执行异步操作,通过commit提交mutation,在mutation中修改store的状态
<2>、store.dispatch 的分发传参时的两种形式(载荷形式,对象形式),载荷形式:store.dispatch('方法名', '传参');对象形式:store.dispatch({ type: ‘方法名’,key: value, [ ... ] })
4、getter — store中state的派生状态
可以理解为 store 的计算属性, 更像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,然后返回结果
说明:通过 getter 拿到的是相当于计算后的值,所以通过对象的方式传值
如果需要传值计算,那么此时相当于是调用getters里面的方法,所以 getter 的值需要是一个方法, 通过双箭头函数返回,传参在后面的箭头函数,第一个箭头函数的state是派生的state状态
5、module
使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象会变得相当臃肿
Vuex 允许我们将 store 分割成模块(module),每个模块拥有自己的 state、mutation、action、getter
注:由于 modules 也是一个对象,渲染数据时要带上对象的key (store.state.module1.名称)
6、vuex辅助函数
mapState
、mapMutations
、mapGetters
、mapActions
<1>、mapState
<2>、mapMutations
<3>、mapGetters
<4>、mapActions
7、vuex 的命名空间
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的,则不同模块有相同命名的mutations、actions时,不同模块对同一命名的 mutation 或 action 都会作出响应;
且模块过多时,在使用辅助函数mapState、mapGetters、mapMutations、mapActions时很难查询引用的state、getters、mutations、actions来自于哪个模块,不便于后期维护
此时我们可通过添加 namespaced: true
的方式使其成为带命名空间的模块(命名空间),当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名
方法一:
方法二:
说明:当开启命名空间后,通过辅助函数获取 store 的值时,若未指定空间名且全局命名空间中没有该变量,将获取不到该变量参数
改变状态方法:不需要额外引入,直接调用方法即可
this.$store.commit("SET_COUNT");
this.$store.commit("SET_NAME", '张三');
this.$store.commit("SET_AGE", 20);