一直在用VueX但是对他的底层逻辑一知半解,因此想写这篇文章理清一下思路。主要了解和解决的问题:
1、VueX到底是干啥用的,解决了什么问题?
2、VueX在实际开发中怎么用?
3、VueX源码中到底是如何实现数据响应式的,以及ctions、getters、mutations如何实现数据修改?
本文章主要梳理的是Vuex底层是如何实现的,理解、读懂vuex的实现机制。本文以VueX4版本为例。
一 VueX是什么
官方给的定义是:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
VueX通俗来说就是状态的集中管理,当要使用的数据嵌套比较深不好取用时,我们就可以把这些参数放到store中集中的进行管理,修改与取用也直接去store中找参数。
如下示例:组件间传值常用props与emit(当然父子组件通信方式还有好几种,本文就不在赘述了)来实现,但是当一个组件套一个组件,父组件如果想取用子孙组件的参数就需要子组件取子孙组件参数、父组件取子组件参数,参数交互比较麻烦,这个时候就可以用到VueX来进行状态管理。
围绕VueX的工作原理图,简要说明一下各核心流程点的主要功能
-
核心概念
- 1.Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
- 2.Dispatch:操作行为触发方法,是唯一能执行action的方法。
- 3.Actions:操作行为处理模块。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发。向后台API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作。该模块提供了Promise的封装,以支持action的链式触发。
- 4.Commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
- 5.Mutations:状态改变操作方法。是Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错。该方法只能进行同步操作,且方法名只能全局唯一。操作之中会有一些hook暴露出来,以进行state的监控等。
- 6.State:页面状态管理容器对象。集中存储Vue components中data对象的零散数据,全局唯一,以进行统一的状态管理。页面显示所需的数据从该对象中进行读取,利用Vue的细粒度数据响应机制来进行高效的状态更新。
- 7.Getters:state对象读取方法,该方法 类似于计算属性computed。图中没有单独列出该模块,应该被包含在了render中,Vue Components通过该方法读取全局state对象。
默认规则:
1、提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。actions不能直接修改state
2、应用层级的状态应该集中到单个 store 对象中。
3、异步逻辑都应该封装到 action 里面。
二 安装与使用
1 安装VueX
1.1 npm
npm install vuex@next --save
1.2 直接下载或者引入
https://unpkg.com/vuex@4
1.3 yarn
yarn add vuex@next --save
2 基本使用
2.1 取值
1 使用辅助函数
computed: {
...mapState({
name: state=> state.base.name
}),
...mapGetters(['nameChange']),
}
辅助函数中参数写法以mapState为例
对象写法:可以更改属性名
…mapState({ name: state=> state.base.name })
…mapState( ‘base’, { name: 'name ’ })
数组写法
…mapState(‘base’,[‘name’])
2 使用store
this.$store.state.base.name //获取参数
this.$store.getters['base/firstName '] // 获取getter的属性firstName
2.2 修改值
VueX规定提交mutation是唯一改变值的方法,所以我们可以直接用commit去球盖
this.$store.commit('base/SET_NAME','张三')
actions通过调用mutation方法去更改
this.$store.dispath('base/SET_NAME','张三')
使用辅助函数修改值
methods: {
...mapMutations({
edithCommit:'base/SET_NAME' // 对方法进行重命名
}),
...mapActions({
edithDispatch:'base/setName'
})
}