阅读时间预计8分钟,读完本文你将收获如下知识点,记得点赞👍哦~
一、啥是Vuex?
Vuex是用来管理Vue的所有组件状态,说白了就是组件中通信的一种高级方式。
Vuex官方文档已经讲解的非常详细,建议通读一遍,本文是自己的学习总结实践和归纳,有些概念和语句借鉴官方。
二、为什么使用Vuex?
在之前的文章组件通信中我们讲了组件中的常用通信方式有props
,$emit/v-on
,$parent / $children & $refs
这三种,他们的局限性在于只能在父子组件中通信,不能在兄弟组件中通信,另外两种是Bus中央总线
、发布订阅模式
可以在任意组件之间进行通信,但是如果在大型项目中难免会有些许瓶颈,组件之间的耦合度较高,那么这时Vuex
就恰到好处的出现了,他能够合理的管理各组件中的状态(通信,方法捕获实现,数据传递),将状态从组建中剥离开来,定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,这样我们的代码将会变得更结构化且易维护。
三、Vuex核心
Vuex
提供一个单例Store
它就相当于一个容器一样,包含着你应用中的state
公共数据,我们通过单例Store
来统一的按照既定规则来动态的管理这些state
,这就是Vuex
的核心。
1.State
state就是一个纯对象,上面有一些状态挂载,而且一个应用应该只有一个
state
在store.js
中
export default new Vuex.Store({
state : {//初始状态
name:'极客James',
height:180,
age:27
}
})
1.1mapState
:
使用 mapState 辅助函数帮助我们生成计算属性,在需要通信的组件中通过
import {mapState} from 'vuex'
引入辅助函数,然后要在计算属性computed
钩子里面进行数据的映射。
mapState
辅助函数使用的三种方式:
- 第一种:计算属性通过箭头函数取返回值
computed:mapStates({
name:state=>state.name,
height:state=>state.name,
age:state=>state.age
})
- 第二种方法:利用ES6的...延展特性 (推荐做法)
computed:{
...mapState([
'name',
'height',
'age'
])
}
- 第三种方法:利用ES6的...延展特性通过对象取值
computed:{
...mapState({
name:state=>state.name,
height:state=>state.height,
age:state=>state.age
})
}
在组件中取数据
<template>
<div class="app">
<div>我是store里面的数据姓名:{{name}}</div>
<div>我是store里面的数据年龄:{{age}}</div>
<div>我是store里面的数据身高:{{height}}</div>
</div>
</template>
输出结果:
2.Getter
可以认为是
store
的计算属性,就像计算属性一样,getter
的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
2.1mapGetter
mapGetter
是getter的一个辅助函数,使用方法和mapState
类似,推荐使用延展...来取值.
3.Mutation
在组件中通过事件方法来进行同步改变Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,同步改变state的唯一方法。
store
中的state
,需要通过commit
提交来响应mutation
中的事件方法。
methods: {
add () {
Store.commit('increment', { number: 10 });
},
reduce () {
Store.commit('reduce');
}
}
另外一种写法:对象风格的提交方式
推荐使用常量替代 Mutation 事件类型还记得在组件通信中讲到的发布订阅
方法进行组件间通信,使用常量来定义事件类型吗?在Vuex
中也是非常推荐使用此办法的,将mutation
中的事件常量整合到一个文件夹mutation-type.js
中,通过export
方式导出.
在mutation-type.js
export const ADD = 'ADD'
export const REDUCE = 'REDUCE'
在store.js
中引入import {ADD,REDUCE} from './mutation-type.js'
import {ADD,REDUCE} from './mutation-type.js'
mutation:{
[ADD](state,payload) {
state.age += payload.number;
},
[REDUCE](state,payload) {
state.age --;
}
}
同样的在需要的组件中引入import {ADD,REDUCE} from './mutation-type.js'
3.1 mapMutation
mapMutation
是mutation
的辅助函数,和state
类似都可以通过...扩展运算来进行直接取值。
4.Action
- Action 提交的是
mutation
,而不是直接变更状态。 - Action 可以包含任意异步操作。
注册一个简单的Action
,并且从外界传值。
store.dispatch
方法触发,在Vue组件中:
另外的写法:参数解构
add({commit}) {
commit('add');
}
4.1 mapAction
mapAction
是action
的辅助函数,便于在Vue组件中调用action里面的事件.
在Vue组件中,可以通过解构mapAction
的方式将映射
methods: {
...mapActions([
'add',
"reduce"
])
}
注意此时:用mapActiono
映射方法后需要传参那么需要写在事件触发的地方上
<button @click="add({number:10})">增加年龄</button>
4.2 组合 Action
组合Action其实就是异步处理多个commit
事件,可以相互调动action
,借助Promise
保证了数据状态的稳定性和有序性。
官方实例:
在store.js
中
store.dispatch('actionA').then(() => {
})
在另外一个 action 中可以异步提交事件:
actions: {
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
推荐阅读:
5.Module
当应用变得非常复杂时,store 对象就有可能变得相当臃肿,为了解决这一问题,我们可以将store
中的五种状态剥离成单个的模型,然后通过一个入口引入.一般在项目开发中在src
目录下创建一个store
的目录然后创建以下文件
在index.js
中引入所有文件,统一挂载在Vuex实例上
main.js
中引入index.js
并挂载到实例Vue上
常用项目结构:
├── index.html
├── main.js
├── api
│ └── ... # 抽取出API请求
├── components
│ ├── App.vue
│ └── ...
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── state.js # 根级别的 state
├── actions.js # 根级别的 action
├── getter.js # 根级别的 getter
├── mutations.js # 根级别的 mutation
├── mutations-type.js # mutation事件常数名
└── modules
├── a.js # a模块
└── b.js # b模块
└── ...
扫一扫下面的二维码,回复学习即可免费领取最新前端学习资料,也希望在前端进阶的路上,我们一起成长,一起进步!