浅谈|浅谈 VueX 状态管理模式

前言

我们知道Vue组件通讯基本的方式有 子传父,父传子,平行兄弟组件通信,那么在简单的应用当中,Vue Store这种单一状态管理基本的方式就可以满足我们的日常需求,但是若要遇到大型复杂系统,你比如说,我有个数据,需要在多个实例,多层实例之间来回传递共享,那么一层一层的接收与发送就显得非常繁琐,并且组件之间的状态管理会显得十分麻烦,那么这个时候我们就应该考虑应用VueX了。
什么是VueX VueXvue状态管理开发模式,以可预测的方式发生变化,那么首先先解释下相关基本组成成分
1.事件组成
  • dispatch : 触发事件,是唯一能执行action的方法
  • commit :状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
  • mutate :状态改变过程
  • render :编译过程
2.基本对象组成
  • state : 存储状态(变量)
  • getters : 可以理解为store 的计算属性,说的通俗一点就是我可以通过getters将state重新赋值,重新定义
  • mutations : 修改状态并且是同步的方法(唯一改变state的途径)
  • actions : 提交的是 mutation,而不是直接变更状态。负责处理Vue Components接收到的所有交互行为。包含同步/异步操作,支持多个同名方法,按照注册的顺序依次触发,该模块提供了Promise的封装,以支持action的链式触发
  • modules : store的子模块,为了开发大型项目,方便模块化状态管理而使用的
*注:VueX不能直接更改状态,必须通过提交(commit) mutations
3.基本流程
1.Vue组件接收状态并且交互,调用dispatch()方法
2.dispatch()方法触发actions里的相关对应方法
3.actions里的相关对应方法如果需要改变state状态,则调用commit()方法
4.commit()方法提交mutation修改state
5.render的过程通过getters对应的计算属性获取到新的state状态
6.重新渲染Components,更新视图
*注:VueX一旦更改了state状态,与之相关的所有组件都会收到相应变化
浅谈|浅谈 VueX 状态管理模式
文章图片
4.接下来我将写一个基于模块化的Vuex状态管理的使用(这里就是使用ModuleStore分割),因为基于单一的状态管理,所有的状态操作都存放在一个对象里,会变得十分繁琐,同样对象会堆得越来越大,那么首先我们先看下基本的结构是什么样子
const store = new Vuex.Store({ state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... }, modules: { a: moduleA, b: moduleB } })

5.首先,我通过一个Demo实例来解释VueX如何使用,结构如下

浅谈|浅谈 VueX 状态管理模式
文章图片
image.png 【浅谈|浅谈 VueX 状态管理模式】
6.这里我做了全局和局部模块拆分的处理,全局store存放在global.js,模块化的以文件为单位,存放在modules文件夹下,最后通过index.js合并导出.同样我用两个子组件ChildAChildB,一个父组件Parents来说明组件之间如何实现全局控制。代码示例如下
  • global.js
/** * Created by Echonessy on 2019.09.29 * 全局store 配置 *///components 执行dispatch('addAction') // 触发actions的addAction方法 //addAction通过commit('add')触发mutations的add方法改变state //getter计算后重新渲染到页面上//golbal state export const state = { golbalNumber:0 } //golbal getters export const getters = { golbalNumber: state => state.golbalNumber+'_golbalGetters', } //golbal mutations export const mutations = { addGolbalMutation:state => {state.golbalNumber++; }, subGolbalMutation:state => {state.golbalNumber--; }, } //golbal actions export const actions = { addGolbalAction ({ commit }) { commit('addGolbalMutation') }, subGolbalAction ({ commit }) { commit('subGolbalMutation') }, }export default { state, getters, mutations, actions }

  • childa.js
/** * Created by Echonessy on 2019.09.29 * childa 模块 配置 */ export const state = { number:1 }export const getters = { childNumber: state => state.number+'_fromChildA', }export const mutations = { addMutation:state => { state.number++; }, subMutation:state =>{ state.number--; } }export const actions= { addAction ({ commit }) { commit('addMutation') }, subAction({ commit }){ commit('subMutation') } }export default { namespaced: true, //在使用模块化的时候,dispatch('childb/addAction') state, getters, mutations, actions }

  • childb.js
/** * Created by Echonessy on 2019.09.29 * childb 模块 配置 */ export const state = { number:1 }export const getters = { childNumber: state => state.number+'_fromChildB', }export const mutations = { addMutation:state => { state.number++; }, subMutation:state =>{ state.number--; } }export const actions= { addAction ({ commit }) { commit('addMutation') }, subAction({ commit }){ commit('subMutation') } }export default { namespaced: true, //在使用模块化的时候,dispatch('childb/addAction') state, getters, mutations, actions }

  • index.js 主入口
import Vue from 'vue' import Vuex from 'vuex' import global from './global'Vue.use(Vuex)const modulesFiles = require.context('./modules', true, /\.js$/); // module 合并 const modules = modulesFiles.keys().reduce((modules, modulePath) => { // set './app.js' => 'app' const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1'); const value = https://www.it610.com/article/modulesFiles(modulePath); modules[moduleName] = value.default return modules }, {})const obj = {} obj.modules = modules; const options = Object.assign(global,obj) const store = new Vuex.Store(options)export default store

7.main.js主入口文件引入
import Vue from 'vue' import App from './App' import router from './router' import store from "./store"; Vue.config.productionTip = false/* eslint-disable no-new */ new Vue({ el: '#app', router, store, components: { App }, template: '' })

8.我们打印index.js里的options,结构如下,我们可以看到整个store的基本结构

浅谈|浅谈 VueX 状态管理模式
文章图片
image.png
9.上面已经讲了 VueX的运行流程,那么我们在组件内如何去修改 state? 我用一个 Parents组件就能够完全说明
  • parents.vue
.child{border: 1px solid #ccc; box-sizing: border-box; padding: 30px; } .single{line-height: 40px; }

10.基本效果

浅谈|浅谈 VueX 状态管理模式
文章图片
11.最后代码地址:demo

    推荐阅读