本篇主要讲vuex的模块化,虽然官网已经讲得比较细致了,但是在实践的时候还是踩了不少坑。今天就在这里把模块化使用过程中的细节都讲清楚,方便大家学习,也方便自己以后复习。
1.Vuex简单介绍
1.1 Vuex是什么
官方:Vuex
是一个专为Vue.js
应用程序开发的状态管理模式,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化(即通过提交mutation
来更新状态)
Vuex
是适用于Vue
项目开发时使用的状态管理工具。把组件中的共享状态抽取出来,以一个全局单例模式管理,采用集中式存储的方式管理应用的所有组件的状态,同时利用Vue.js
的响应式机制来进行高效的管理与更新。并且只能通过提交mutation
的方式来进行数据修改,主要是为了保证数据状态的可预测。
1.2 为什么使用Vuex
在Vue
中最重要的是数据驱动和组件化,每个组件都有自己的data
,template
和methods
,data
是数据,我们也叫做状态,通过methods
中的方法改变状态来更新视图。在单个组件中修改状态更新视图特别方便,但实际开发复杂应用时,经常会遇到多个组件共享同一个状态,或者多个组件会去更新同一个状态。在涉及组件较少时,我们可以通过组件间通信去维护共享数据。但是如果涉及组件较多时,组件之间的数据通信关系会变得错综复杂,难以维护。
这时就需要Vuex
进行状态管理,将共享数据抽取出来进行统一存储管理。
Vuex主要解决的问题
● 多个视图依赖同一个状态
● 来自不同视图的行为需要变更同一个状态
对于多个视图依赖统一状态的情况,传参的方法对于多层嵌套的组件将会非常繁琐,并且兄弟组件间的状态传递更是繁琐。
对于第二个问题,我们会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝,这两种方式容易导致后期维护代码的难度较大。
使用Vuex的好处
● 能够在Vuex中集中管理共享数据,易于开发和后期维护
● 能够高效地实现组件之间的数据共享,提高开发效率
● 在Vuex中的数据都是响应式的
1.3 Vuex的状态管理模式
通过官方的这张图我们可以看得出来,Vuex
的状态管理模式主要是实现了一个单项数据流,在全局拥有一个State
存放数据,所有修改State
的操作必须通过mutation
进行。所有异步接口需要走Action
,并且Action也是无法直接修改State
的,还是需要通过mutation
来修改State的数据。最后根据State
的变化,渲染到试图上。Vuex
运行机制依赖Vue
内部数据双向绑定机制,需要new
一个Vue
对象来实现响应式,所以Vuex
是一个专门为Vue.js
设计的状态管理库。
1.4 Vuex Modules
关于Vuex
的使用这里就不过多的赘述了,需要了解的可以直接点击Vue.js
官网进行学习。现在我们来说一下Vuex
的模块化。
1.4.1 为什么要用到Vuex Modules
在Vuex
中应用的所有需要共享和被修改的数据源都存放在state
对象中,当应用较为复杂,需要共享的数据较多时,state
对象以及store
对象都会变得很臃肿,不利于代码维护。并且大多应用都会根据业务分为不同的功能模块,很多情况下不同模块之间的数据交互并不密切,如果我们能将store
也分割为不同模块,每个模块管理不同的数据,会使数据管理起来更加结构清晰,方便管理。
那么为了解决以上的问题,Vuex
允许我们将store分割成模块。每个模块拥有自己的state
、mutation
、action
、getter
并且可以嵌套子模块。
1.4.2 Vuex Modules简单使用
我们在src目录下建立我们的store文件夹,用来写一些vuex module的简单使用。
// index.js
import Vue from 'vue'
import Vuex from 'vuex'
import {
moduleA } from './moduleA'
import {
moduleB } from './moduleB'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
name: 'index'
},
mutations: {
increment(state, payload) {
state.count += payload.amount;
console.log("mutations" + state.name)
},
},
actions: {
incrementAsync({
state, commit }, products) {
setTimeout(() => {
console.log("actions" + state.name)
commit('increment', products)
}, 1000)
}
},
modules: {
moduleA, moduleB },
getters: {
getCount: (state) => {
return "store被调用了" + state.count + "次"
}
}
})
// moduleA.js
export const moduleA = {
state: {
nameA: "moduleA",
countA: 0
},
mutations: {
incrementA(state, payload) {
state.countA += payload.amount;
console.log("mutations" + state.nameA)
}
},
actions: {
incrementAsyncA({
commit }, products) {
setTimeout(() => {
commit('incrementA', products)
console.log("actions" + state.nameA)
}, 1000)
}
},
getters: {
getCountA: (state, getters) => {
console.log("getter" + state.nameA)
return state.nameA + "被调用了" + state.countA + "次"
}
}
}
// moduleB.js
export const moduleB = {
state: {
nameB: "moduleB",
countB: 0
},
mutations: {
incrementB(state, payload) {
state.countB += payload.amount;
console.log("mutations" + state.nameB)
}
},
actions: {
incrementAsyncB({
commit }, products) {
setTimeout(() => {
commit('incrementB', products)
console.log("actions" + state.nameB)
}, 1000)
}
},
getters: {
getCountB: (state, getters) => {
console.log("getter" + state.nameB)
return state.nameB + "被调用了" + state.countB + "次"
}
}
}
<template>
<div class="hello">
<div>
{
{name}}
<button @click="incrementFun">{
{count}}</button>
{
{getCount}}
</div>
<div>
{
{nameA}}
<button @click="incrementFunA">{
{countA}}</button>
{
{getCountA}}
</div>
<div