vue中的状态管理Vuex
安装vuex
npm install vuex --save
使用vuex
在src目录下新建一个store文件夹, 并在store下新建一个index.js
在main.js中引入store
// main.js
import store from './store';
new Vue({
el: App,
store,
render: (h) => h(App)
})
// index.js
// 引入vue
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
// 使用Vuex插件
Vue.use(Vuex);
// 暴露出store
var store = new Vuex.Store({
state:'',
mutations: '',
actions: '',
getters: '',
});
export default store;
store的组成
State
state用来定义属性
Mutations
mutations中定义了一个个的方法,用来修改属性值,因为Store不可以直接通过this.$store.state.xxx = xxx来修改属性值
mutations中的函数必须是同步操作,不能包含异步操作
Actions
actions存在的意义是假设你在修改state的时候有异步操作,vuex不希望你将异步操作放在mutations中,而是将其放在actions中,并且将actions暴露给用户,借此操作mutations中的方法修改state
Getters
getters是读取修饰器,主要目的是在读取state时,可以加工返回值
辅助函数
Vuex中提供了4个辅助函数来帮助使用store
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
mapState与mapGetters只能在computed中使用,与正常的computed中的函数一起使用时需要用扩展运算符,然后在mapState或mapGetters函数的数组中放入对应的state或getters中的名称
通过辅助函数获取到的值和方法可以使用this.xxx调用
具体使用方法后面会说
按照模块拆分Store
当我们项目中数据较多,可以将数据按照功能划分为多个module
假设当前项目有一个user用户信息模块,有一个product商品信息模块
我们可以在src/store目录下新建一个components文件夹,并在components中新建一个user.js 和 product.js
// user.js
const state = {};
const mutations = {};
const actions = {};
const getters = {};
export default user = {
namespaced: true
state,
mutations,
actions,
getters,
}
// product.js
const state = {};
const mutations = {};
const actions = {};
const getters = {};
export default product = {
namespaced: true
state,
mutations,
actions,
getters,
}
// index.js
// 引入user和product模块
import user form './components/user.js'
import product form './components/product.js'
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
var store = new Vuex.Store({
// 在modules属性中使用user和product
modules: {
user,
product
}
});
export default store;
namespaced属性
- 当定义的模块
module中含有namespaced: true属性时,表示开启了模块命名空间 - 默认情况下,模块内部的
sactions、mutations、getters是注册在全局命名空间的,可以直接调用,这样容易和其他模块中的state或方法名重复,所以需要添加namespaced: true来开启命名空间,区分和其他模块中冲突的state和方法。开启命名空间后访问模块中的内容需要带上模块名。
使用store(包括开启命名空间和未开启命名空间)
-
state
- 开启命名空间 / 未开启命名空间
- 插值表达式使用:
$store.state.模块名.属性名 - 映射为辅助函数 - 数组格式:
...mapState('模块名', ['属性名']) - 映射为辅助函数 - 对象格式:
...mapState({'属性名': state => state.模块名.属性名}) - methods中使用:
this.$store.state.模块名.属性名
- 插值表达式使用:
- 开启命名空间 / 未开启命名空间
-
mutations
- 未开启命名空间
this.$store.commit('mutations中方法名',实参)- 映射为辅助函数 - 数组格式:
...mapMutations(['mutations中方法名']]) - 映射为辅助函数 - 方法调用:
this.mutations中方法名(参数)this['mutations中方法名'](参数)
- 开启命名空间
this.$store.commit('模块名/mutations中方法名',实参)- 映射为辅助函数 - 数组格式:
...mapMutations(['模块名/mutations中方法名']]) - 映射为辅助函数 - 方法调用:
this['模块名/mutations中方法名'](参数) - 映射为辅助函数 - 属性格式:
...mapMutations('模块名',['mutations中方法名']) - 映射为辅助函数 - 方法调用:
this.mutations中方法名(参数)this['mutations中方法名'](参数)
- 未开启命名空间
-
actions
- 未开启命名空间
this.$store.dispatch('actions中方法名',实参)- 映射为辅助函数 - 数组格式:
...mapActions(['actions中方法名']]) - 映射为辅助函数 - 方法调用:
this.actions中方法名(参数)this['actions中方法名'](参数)
- 开启命名空间
this.$store.dispatch('模块名/actions中方法名',实参)- 映射为辅助函数 - 数组格式:
...mapActions(['模块名/actions中方法名']]) - 映射为辅助函数 - 方法调用:
this['模块名/actions中方法名'](参数) - 映射为辅助函数 - 属性格式:
...mapActions('模块名',['actions中方法名']) - 映射为辅助函数 - 方法调用:
this.actions中方法名(参数)this['actions中方法名'](参数)
- 未开启命名空间
-
getters
-
未开启命名空间
this.$store.getters.属性名- 映射为辅助函数 - 数组格式:
...mapGetters(['getters中方法名']])
-
开启命名空间
-
this.$store.getters['模块名/属性名'] -
映射为辅助函数 - 数组格式:
...mapGetters(['模块名/getters中方法名']]) -
映射为辅助函数 - 方法调用:
this['模块名/getters中方法名'] -
映射为辅助函数 - 属性格式:
...mapGetters('模块名',['getters中方法名']) -
映射为辅助函数 - 方法调用:
this.getters中方法名
-
-
为什么Vuex要通过mutations修改state,而不能直接修改state,也不建议在actions中修改state
- 首先保证了
store中数据的单向流动性,组件只能使用数据而不能修改数据(非生产模式),严格模式下直接修改state会报错 mutations只能进行同步操作,而操作state和actions中可以是异步操作。如果异步操作state时,其他地方修改了state,会导致程序的混乱vue-devTools会记录每一次的mutations操作,可以清楚看到每一次操作后state的变化,方便调试而actions中的操作则不会被观测记录下