Vuex_新年篇
文章目录
前言
本文部分需要,可以先不看,到用到这个知识点再来补
CSDN:ES6之-优雅的Promise
CSDN:Vue CLI配置原理详解
CSDN:Vue _Devtools
我每次在写博客的时候,都会有前言多多少少讲讲这个知识点为什么存在,希望大家不要嫌啰嗦,我当然清楚每个人都希望搜索不会的知识的时候,有现成组织好的语法,或者一步步带着你去操作,就是所谓的干货,但是写干货的人太多了,就是因为这样导致太多的网络水文,越到难的地方你就越不知道该怎么去分辨,无法理解的大量记忆是非常难受的,其实我们在学习的过程中应该多去思考这些知识点为什么出现,怎么出现,当我们带着这样一种疑问去学习的时候,你真的和别人的理解是完全不一样的,然后我们才去学习这个东西它到底是怎么用的(当然每个人都有自己的学习方式,就像先上手在深入学习,这都是无所谓的),问题是哪怕你事先不知道它是干什么的,你带着疑问去学习,你也会比别人多上一些思考,久而久之,遇到问题的思路是别人无法比拟的
首先还是官方话语:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式
。它采用集中式存储管理
应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
一、Vuex的状态管理模式?
这些高大上的名词我们先放一边,说白了,
状态管理的这个状态无非就是一些
数据变量
(能使 多个组件共享的变量)
Vuex就是:我们要对这些状态进行集中式的管理(全都放在一个顶层Vue实例的对象中,让所有组件共享)
这时大家可能有疑问,多个组件共享变量这种事情本身也不难做到啊,复杂的是我们无法让这些庞大且关系复杂的数据变成响应式的,而Vue.js本身就是响应式
的,所以由Vue官方进行封装设计出来的Vuex也是理所当然的了
Vue官方把组件的共享状态抽取出来,以一个全局单例模式管理,在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
二、Vuex管理什么状态?
像父子组件的通信这种单一的映射关系就不需要加入到我们的Vuex中了
我们仔细想想在开发中,什么东西需要我们许多组件进行共享,并实时响应呢
比如QQ、微信的登陆状态,头像,你所在的位置。博客的粉丝数量,访问量等等,这些东西一旦改变我们确实是需要在很多组件页面中都要做到实时的渲染的
我们从一个简单的 Vue 计数应用开始:
<template>
<div id="app">
<h2>{{count}}</h2>
<button @click="count++">+</button>
<button @click="count--">-</button>
</div>
</template>
<script>
export default {
name:'App',
data(){
return{
count:100
}
},
methods:{
}
}
</script>
<style>
</style>
这个状态自管理应用包含以下几个部分:
- state
- view
- actions
state存放counter等一些数据的状态,counter需要在view视图中渲染, view上可以出现一些action来修改state,循环往复,这就是Vue的`单向数据流` |
以下是一个表示“单向数据流”理念的简单示意:
但是做前端的小盆友都清楚,我们的应用大多都是多个组件共享状态时,单向数据流的简洁性很容易被破坏:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
对于第一点,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
对于第二点,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,这就需要大量的数据流进行不断交互和渲染,Vue给你了如下的导图(从单项到多项),你可以先尝试理解一下,下面我们会深入的讲一讲
三、Vuex的安装
还不会脚手架的话请移步: |
脚手架无论2、3,把vuex勾选上安装就OK了,这是我的版本,注意如果你的webpack版本过高像我这样,推荐直接用脚手架安装vuex,因为需要的版本都很高,当然你也可以在package.json里写上vuex的版本直接npm install
不是脚手架的话先安装依赖 |
npm install vuex --save
- 新建一个store文件夹里面新建index.js文件
- 然后使用我们引入插件的方式:Vue.Use() 就好了,这里就不细讲
- 如果出现错误请一定要检查你的vuex版本是否和webpack版本对应
四、Vuex五大核心
首先每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态(state),
我们在store/index.js创建store实例并导出,store(仓库)其中有五个核心部分,我先提前对五个部分进行了小的概述,方便你学习的过程中进行记忆
s
t
o
r
e
:
{
s
t
a
t
e
G
e
t
t
e
r
s
M
u
t
a
t
i
o
n
A
c
t
i
o
n
M
o
d
u
l
e
store:\begin{cases} state\\Getters\\ Mutation\\ Action\\ Module\end{cases}
store:⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧stateGettersMutationActionModule
Vuex 和单纯的全局对象有以下两点不同:
- Vuex 的状态存储是
响应式
的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 - 你
不能直接改变 store 中的状态
。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
好了,接下来我们一个个来讲,因为需要方便展示,我们把大部分内容都放在App.vue里,在真正的项目中是需要抽离出来的,项目组织
在最后会讲到
1.State
存放状态(参数) |
this.$store.state.变量名 就可以拿到变量
我们在index.js中定义一个count变量
直接就可以在各个组件比如App.vue中使用
这里就要注意了,我们不能再像以前的计数方式直接定义方法去修改它,Vue官方专门给了我们一个特性用于修改,通过五大核心的Mutation
我们继续拿这个图来看,我们始终是遵循着这张图的,所以这里的state可以被渲染在Vue组件中,但不能直接去在实例中操作state,我们需要通过Mutations方法
你可能有个疑问,你怎么把actions跳过去了,这个action是专门针对于异步操作的
为什么要这么复杂呢,看到Devtools
了吗,这就是Vue专门为vuex设计的插件,试想如果我们的一个count在App.vue中被修改过,在其他组件也进行了修改,如果出错了,我们怎么才能知道在哪个组件中出错了,这就需要一个插件对我们的Vuex的操作进行监控
State单一状态树:
就像我们国家在储存个人信息的时候,我们从出生到死亡的所有信息不是被一个地方集中管理的,而是有什么学校档案,房产信息,医疗信息,婚姻信息等等都被分散在各地,这是为了保证信息的安全性,但是在我们开发的项目中就不存在这种顾虑了
- 统一管理所有state数据并产生一个树的视图,可以很清晰的展现给大家
- 并且储存在多个的state中,会让日后的开发和维护的压力倍增,这就不是处理问题了,而是问题复杂化
2.Mutation
修改状态(state的值) |
Mutation由两部分构成:
M
u
t
a
t
i
o
n
:
{
事
件
类
型
(
t
y
p
e
)
回
调
函
数
(
第
一
个
参
数
就
为
s
t
a
t
e
)
Mutation:\begin{cases} 事件类型(type)\\回调函数(第一个参数就为state)\end{cases}
Mutation:{事件类型(type)回调函数(第一个参数就为state)
在index.js中的Mutation中定义两个函数,state是vue给出的参数,可以拿到上面的state变量
下面代码中mutation中的方法名就是事件类型
this.$store.commit(‘increment’)这里就是调用事件类型
我们在mutation里面定义两个修改state的方法
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
},//存储状态
mutations: {
// 方法
increment(state){
state.count++
},
decrement(state){
state.count--
},
},//修改状态
})
这样我们在App.vue中在定义两个监听button的函数,让这两个函数调用仓库中Mutation的函数来修改state
在这里我们this.$store.commit(‘函数名’)就可以执行Mutation里的函数
这里的increment
和decrement
被称作Mutations的事件类型
<template>
<div id="app">
<h1>APP组件</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
</div>
</template>
<script>
export default {
components:{
},
data(){
return{
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
}
}
</script>
<style>
#app {
}
</style>
这样我们就可以用Mutation做到修改state
①Mutations方法传参
index.js中我们写入increment(state,counter)
这第二个参数就是待传入的值
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
},//存储状态
mutations: {
// 方法
increment(state){
state.count++
},
decrement(state){
state.count--
},
incrementCount(state,counter){
state.count+=counter
}
},//修改状态
})
App.vue中我们写入一个subCounter方法,用button监听点击并传入参数5,这样就可以实现参数的传递
<template>
<div id="app">
<h1>APP组件</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
<button @click="subCounter(5)">+5</button>
</div>
</template>
<script>
export default {
components:{
},
data(){
return{
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
subCounter(counter){
this.$store.commit('incrementCount',counter)
}
}
}
</script>
<style>
#app {
}
</style>
其实Vue官方给出的这个参数有个专有名词叫payload(载荷)
,你输出payload不难发现它其实是一个对象,你所传入的counter只是其中一个属性所以当你用payload作为参数名时,你需要payload.counter
②Mutation的另一种传参方式
上文:commit(‘事件名’,参数)
此:commit一个对象
注意上面提到的payload
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
},//存储状态
mutations: {
// 方法
increment(state){
state.count++
},
decrement(state){
state.count--
},
//这是Mutation普通提交
incrementCount(state,counter){
console.log(counter)
state.count+=counter
},
//这是Mutation封装提交,
incrementCounts(state,payload){
console.log(payload)//对象
console.log(payload.counter)//取出对象中传入的参数
state.count+=payload.counter
},
},//修改状态
})
App.vue里我们再写入一个 +10的按钮 用来与 普通提交的+5按钮 来区分
<template>
<div id="app">
<h1>APP组件</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
<button @click="subCount(5)">+5</button>
<button @click="subcounts(10)">+10</button>
</div>
</template>
<script>
export default {
components:{
},
data(){
return{
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
//这是Mutation普通提交
subcount(counter){
this.$store.commit('incrementCount',counter)
},
//这是Mutation封装提交,把counter传入一个对象里
subcounts(counter){
this.$store.commit({
type:'incrementCounts',
counter
})
},
}
}
</script>
<style>
#app {
}
</style>
点击+5(普通提交)
点击+10(封装提交)
③Mutation的响应式规则
当你在state中初始化状态的时候,这些属性都会被加入到响应式系统中,而响应式系统会监听属性的变化,当属性发生变化时,会通知所有界面中用到该属性的地方,让界面发生刷新
可Vuex的响应式也有他自己的规则:
- state中的数据是提前初始化好的
- 拿一个state的对象举例,如果在组件中想要给这个对象添加新属性必须使用Vue.set()方法
但现在Vue已经做出了更新,支持新增属性的响应式功能
在老版本的Vue中,第二行这种往info对象中直接添加新属性是不被允许的,因为响应式原理仅支持一开始就被定义的属性
不过新的版本现在也支持这种添加属性了
④使用常量替代 Mutation 事件类型
使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码和作者对整个 app 包含的 mutation 一目了然:
新建store/mutation-types.js
export const IN_CREMENT = 'increment'
store/index.js
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
},//存储状态
mutations: {
// 使用常量
[IN_CREMENT](state){
state.count++
},
decrement(state){
state.count--
}
},//修改状态
})
在App.vue中引入常量IN_CREMENT
<template>
<div id="app">
<h1>APP组件</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
</div>
</template>
<script>
import {
IN_CREMENT
} from './store/muatation-type';
export default {
components:{
},
data(){
return{
}
},
methods:{
addtion(){
this.$store.commit(IN_CREMENT)//常量方式
},
subtraction(){
this.$store.commit('decrement')
},
}
}
</script>
<style>
#app {
}
</style>
用不用常量取决于你——在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。
⑤Mutation 必须是同步函数
Mutation是同步函数是因为vuex的插件Devtools,我们在使用插件进行捕获我们的各种操作的时候,是非常清晰明了的,
但在 mutation 中混合异步调用
会导致你的程序很难调试。例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。
在 Vuex 中,mutation 都是同步事务:
store.commit('increment')
// 任何由 "increment" 导致的状态变更都应该在此刻完成。
这就要用到我们的Action 了,来重新回顾一下这个图
3.Getters
渲染之前对状态的处理 |
什么意思呢,就是我们现在有一个count变量,我们不想每次单纯的展示它,想展示它的平方
我们在index.js的getters中定义powerCount
方法
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
},//存储状态
mutations: {
// 方法
increment(state){
state.count++
},
decrement(state){
state.count--
},
},//修改状态
getters: {
powerCount(state) {
return state.count * state.count
}
},//渲染之前修改或处理状态
})
App.vue中可以直接调用
$store.getters.方法名
<template>
<div id="app">
<h1>APP组件</h1>
<h1>-------------------------------------------------</h1>
<h1>state内容</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
<h1>-------------------------------------------------</h1>
<h1>getters内容</h1>
<h2>{{$store.getters.powerCount}}</h2>
<h1>-------------------------------------------------</h1>
</div>
</template>
<script>
export default {
name:'App',
data(){
return{
count:100
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
}
}
</script>
<style>
</style>
现在我们又有新的需求,我们继续在index.js中定义一个star数组对象,并且想要在组件中渲染的时候只展示年纪小于二十岁的人物对象信息
- index.js定义star对象
- getters里面写入一个方法运用filter进行判断并返回
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
star:[
{id:100,name:'kobe',age:32,height:198},
{id:101,name:'curry',age:10,height:181},
{id:102,name:'james',age:34,height:197},
{id:103,name:'kris',age:19,height:180}
],
},//存储状态
mutations: {
// 方法
increment(state){
state.count++
},
decrement(state){
state.count--
},
},//修改状态
getters: {
powerCount(state) {
return state.count * state.count
},
ArraySort(state){
return state.students.filter( s =>{
return s.age<20
})
},
},//渲染之前修改或处理状态
})
我们在App.vue里
$store.getters.ArraySort(getters里的方法名)
<template>
<div id="app">
<h1>APP组件</h1>
<h1>-------------------------------------------------</h1>
<h1>state内容</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
<h1>-------------------------------------------------</h1>
<h1>getters内容</h1>
<h2>{{$store.getters.powerCount}}</h2>
<div class="array">经过筛选后对象为:</div>
<div>{{$store.getters.ArraySort}}</div>
<h1>-------------------------------------------------</h1>
</div>
</template>
<script>
export default {
name:'App',
data(){
return{
count:100
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
}
}
</script>
<style>
.array{
color:red;
font-size:28px
}
</style>
getters方法传参
- ArraySort():选择输出
- ArraySorts():输出对象的个数
- ArraySortPersonal():参数是人为定义的:
$store.getters.ArraySortPersonal(30),我们设置参数30就可以输出年纪大于30岁的人物对象信息
index.js
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
star:[
{id:100,name:'kobe',age:32,height:198},
{id:101,name:'curry',age:10,height:181},
{id:102,name:'james',age:34,height:197},
{id:103,name:'kris',age:19,height:180}
],
},//存储状态
mutations: {
// 方法
increment(state){
state.count++
},
decrement(state){
state.count--
},
},//修改状态
getters: {
powerCount(state) {
return state.count * state.count
},
ArraySort(state){
return state.students.filter( s =>{
return s.age<20
})
},
ArraySorts(state,getters){
return getters.ArraySort.length
},
ArraySortPersonal(state){
return function(age) {
return state.students.filter(s => {
return s.age > age
})
}
},
},//渲染之前修改或处理状态
})
App.vue
<template>
<div id="app">
<h1>APP组件</h1>
<h1>-------------------------------------------------</h1>
<h1>state内容</h1>
<h2>{{$store.state.count}}</h2>
<button @click="addtion()">+</button>
<button @click="subtraction()">-</button>
<h1>-------------------------------------------------</h1>
<h1>getters内容</h1>
<h2>{{$store.getters.powerCount}}</h2>
<div class="array">经过筛选后对象为:</div>
<div>{{$store.getters.ArraySort}}</div>
<div>对象个数为:{{$store.getters.ArraySorts}}</div>
<div>任意传入参数获得的对象为:{{$store.getters.ArraySortPersonal(30)}}</div>
<h1>-------------------------------------------------</h1>
</div>
</template>
<script>
export default {
name:'App',
data(){
return{
count:100
}
},
methods:{
addtion(){
this.$store.commit('increment')
},
subtraction(){
this.$store.commit('decrement')
},
}
}
</script>
<style>
.array{
color:red;
font-size:28px
}
</style>
4.Action
action就是vuex中针对于对数据的提交无法直接对Mutation进行异步操作而存在的 |
其实把异步编程例如setTimeout,放入action里面就好了,
就像state是Mutation和getters的参数一样,action也有自己的参数:context
import { createStore } from 'vuex'
export default createStore({
state: {
count:100,
info:{
name:'王光迪',
age:19,
condition:single
}
},//存储状态
mutations: {
updateInfo(state){
state.info.condition="别改了,再改也是single"
}
},//修改状态
getters: {
},//渲染之前修改或处理状态
action:{
// context:上下文
aUpdateInfo(context){
setTimeout(()=>{
context.commit('updateInfo')
},1000)
}
}
})
记得Vue给出的图吧,Mutation的
commit
之前 有action的diapatch
<template>
<div id="app">
<h1>action内容</h1>
<button @click="updateInfo()">修改个人信息</button>
</button>
</div>
</template>
<script>
export default {
name:'App',
data(){
return{
count:100
}
},
methods:{
updateInfo(){
this.$store.dispatch('aUpdateInfo')
}
}
}
</script>
<style>
</style>
梳理一下这个顺序:不是往常的commit->mutation
而是dispatch->action(aUpdateInfo)->在aUpdateInfo中进行commit->Mutation
还记得Promise这个东西吗,针对于异步编程Vue怎么会舍得不用它
Action–Promise
index.js
我们在actions中继续用aUpdateInfo这个函数,因为需要演示所以传入了参数payload
想必大家已经多多少少了解Promise了,我们先return 一个Promise实例,rejected就先不传了,只传一个resolved
注意了!!,我们的.then()不写在这里
App.vue
我们把.then()写到了dispatch后面
其实你认真的看过我上面写的提交顺序就可以轻松理解
dispatch->action(aUpdateInfo)->在aUpdateInfo中进行commit->Mutation
我们先执行this.$store.dispatch(这时不会往后执行.then(),因为触发条件时resolve() -->到aUpdateInfo执行commit,然后console.log一次
最后在Promise实例中执行resolve()–>这么就可以回到.then()
看看我们最终的输出,先是控制台输出payload—>resolve()到.then()控制台输出’完成了提交’—>控制台输出res
你学废了吗
5.Moudles
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,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
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
不过需要注意的是,随着模块化,每个核心的使用方式也略有不同 |
state:
我们在组件中使用不能像往常中$store.state.name
而是: this.$store.state.a.name
这里的a也是因为modules里面定义的
细心的可以发现,state这个对象里哪有a,这是被Vue官方设计好的特性,所以这里记住就好了
modules: {
a: moduleA,
b: moduleB
}
Mutation
和state不一样,不管你在哪个模块中的Mutation定义的方法,由于这里是commit(提交),所以还是
this.$store.commit(‘方法名’,参数)
只不过你要保证,在所有模块的Mutations里面你定义的方法名不可以重复,因为他会优先commit大的store模块
getters
和Mutation类似,使用方法也和以前一样,且方法名不可重复
$store.getters.方法名
在store的getters函数中写入的方法可传入第三个参数rootState,可以取到所有模块根模块的state的属性
FullName(state,getters,rootState){
return rootState.name//这里取到的是根state下的name属性
}
actions
上面讲到,actions是通过组件中定义方法执行this.$store.dispatch(‘函数名’),
这个函数在actions中
然后在这个函数里面commit Mutation里面的方法名
actions:{
aUpdateInfo(context){
context.commit('函数名')
}
}
这里的更改是,A模块只能commitA模块中Mutation的方法
也就是在本区域下模块进行
其实并不难记 |
state因为是存放数据的地方,数据本身就被分模块存起来,我们要取是分模块取,所以会有什么.a.b
Mutation是因为是要提交(commit)提交到一个地方,所以只需要不重复方法名就好
getters是因为渲染之前对数据的处理,虽说是处理数据,但这些处理数据的函数都是在getters里面定义好的,所以只是在组件里
$store.getter.函数名
调用,你可以理解为在整个大仓库里调用,所以不需要分模块,但处理数据有根state参数(rootState)
action就是本模块进行处理
六、项目结构
Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
-
应用层级的状态应该集中到单个 store 对象中。
-
提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
-
异步逻辑都应该封装到 action 里面。
只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter
分割到单独的文件
再引入到index.js就好了。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
s t o r e : { i n d e x . j s a c t i o n . j s g e t t e r s . j s M u t a t i o n . j s M o d u l e . j s { A 模 块 B 模 块 C 模 块 store:\begin{cases} index.js\\action.js\\getters.js\\ Mutation.js\\ Module.js\begin{cases} A模块\\B模块\\ C模块\\ \end{cases}\end{cases} store:⎩⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎧index.jsaction.jsgetters.jsMutation.jsModule.js⎩⎪⎨⎪⎧A模块B模块C模块
index.js
import { createStore } from 'vuex'
import getters from './getters'
import Mutations from './Mutations'
import actions from './actions'
import moduleA from './modules/moduleA'
const state = {...}
export default createStore({
state,
mutations,
actions,
getters,
modules:{
a:moduleA
}
})