一、vuex是干什么的
当你的项目中,需要共享应用中组件状态的时候,就会用到vuex,称之为状态管理器。简单来说,就是公共变量,意在全局把控公共数据,共享全局数据。
小型项目,可以用localStorage存储公共变量,共享数据。
相关文章(vuex具体使用方法):vuex的初始化
二、核心
首先创建store实例,并注册:
//创建store实例
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({ ...options })
//在入口文件添加store
import store from "./store"
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
options重要选项:State Getters Mutations Actions Modules
1.state
Vuex 使用单一状态树——用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。
state是全局变量组成的全局对象,通过this.$store.state
可以获取这个对象。
获取state的值方式:
this.$store.state
- mapState语法糖,即辅助函数
写法( 一般获取公共变量都放在computed中获取,使用 mapState 辅助函数生成计算属性 )
computed:{
...mapState({
state1: 'state1', // 第一种写法
state2: (state) => state.state2, // 第二种写法
})
//或者
...mapState([
'state1',
'state2'
])
},
state可以直接修改值,比如this.$store.state.state1 = '12ddwd'
,state值就会改变。
2.Getters
有时候我们需要从 store 中的 state 中派生出一些状态,就是需要在全局变量的基础上,获取全局变量相关的属性值
Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
Getter 接受 state 作为其第一个参数:
export const state1 = (state)=>{
return state.state1
}
export const oneTodos = (state )=> {
return state.todos.filter(todo => todo.done)
}
获取方式:
this.$store.getters.state1
- mapGetters(与mapState类似)
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'state1',
'state2',
])
}
3.Mutations
更改 Vuex 的 store 中的状态的 唯一方法 是提交 mutation!
mutation是通过直接改变状态(全局变量state)的方式改变state
mutation 必须同步执行
mutations修改全局状态,基本写法
- mutations.js – 相当于生成了修改全局变量的事件函数,触发需要事件驱动
export default {
change1: (state,options)=>{
state.state1 = options;
}
}
- 在组件中修改state1的值 – 事件触发commit
this.$store.commit('change1','修改数据11111111111')
mutations常量写法
我们经常使用常量来替代 mutation 事件类型,如下
export const SET_STATE1= 'SET_STATE1'; //mutation-types.js
import * as types from './mutation-types';
export default {
[types.SET_STATE1](state, cid) {
state.state1= cid;
},
}
this.$store.commit('SET_STATE1','修改数据11111111111')
mapMutations语法糖
mutations.js方法不变
在组件中提交mutation的方法
methods: {
...mapMutations([ //如果mutations定义的常规方法
'change1', // 将 `this.change1(val)` 映射为 `this.$store.commit('change1',val)`
]),
//二个用法多一点(常量命名)
...mapMutations({ //如果mutations定义的常量方法
add: 'SET_STATE1' // 将 `this.add(val)` 映射为 `this.$store.commit('SET_STATE1',val)`
})
}
//调用:
this.change1('修改后的值')
this.add('修改后的值')
4.Actions
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
Actions常规写法
- Action 函数定义
它接受一个与 store 实例具有相同方法和属性的 context 对象,有commit方法和state属性等
export const selectPlay = function ({commit, state}, {list, index}) {
// 提交mutation
commit( 'playList', list)
commit( 'currentIndex', index)
commit( 'fullScreen', true)
}
- 触发actions事件函数
Action 通过 store.dispatch 方法触发:
store.dispatch('selectPlay')
mapActions
actions函数定义不变
在组件中使用方式改变,即触发方式
import { mapActions } from 'vuex'
export default {
// ...
methods: {
//第一个用法多一点
...mapActions([
'selectPlay ' // 将 `this.selectPlay(amount)` 映射为 `this.$store.dispatch('selectPlay', amount)`
]),
...mapActions({
selectPlay : 'selectPlay' // 将 `this.add()` 映射为 `this.$store.dispatch('selectPlay')`
})
}
}
//调用:
this.selectPlay({
list: playArr,
index
})
5.Modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。 为了解决这个问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
注意:
modules模块中的state不能通过this.$store.state
获取,必须加上module的命名空间,比如:this.$store.moduleA.data1
但是getters和mutations
能正常使用
- 在这个模块中,getter正常赋值,第一个是state对象(局部全局状态中,state指的是当前的局部state)
get_data(state){
return state.data
}
- mutations有些不同
change_data(state,options){
//在这里获取局部state中的data变量的方法
//console.log(this.getters.get_data)
//console.log(this.state.module_1.data)
//这里this.$store不存在
//修改全局状态的方法
state.data = options; //第一种,常见,直接替代赋值
this.state.module_1.data = options;//第二种,与第一种类似,改变局部state的赋值
//第三种,修改,没有新的赋值的属性,依然存在,且值不变
// let add = this.getters.get_data;
for (let key in add) {
if (options[key]!==undefined) {
add[key] = options[key]
}
}
}
三、总结
- state中的状态数据,只能通过mutation来修改
- getters是来获取state中的数据,只读
- actions是处理mutation的
- modules是来分模块处理全局状态的
mapState
mapGetters
是来获取全局变量的,作为计算属性处理
mapMutations
mapActions
相当于事件处理函数,放在methods中,等待触发
mapState === this.
s
t
o
r
e
.
s
t
a
t
e
1
m
a
p
G
e
t
t
e
r
s
=
=
=
t
h
i
s
.
store.state1 mapGetters === this.
store.state1mapGetters===this.store.getters.state1
mapMutations === this.$store.commit(‘SET_STATE1’,‘修改数据11111111111’)
mapActions === this.store.dispatch(‘selectPlay’)
map后面可以是对象,也可以是数组,数组里放原方法名或属性名;对象,自己定义新的方法名或属性名
理解这些,再使用vuex就没什么问题了!