Vue笔记-系列
Vue笔记[一]-初识
Vue笔记[二]-组件化
Vue笔记[三]-ToDoList
Vue笔记[四]-动画、Vuex
Vue笔记[五]-路由
Vue笔记[六]-Vue3
Vite、Pinia、Router
QX-AI
GPT-4
QX-AI初始化中...
暂无预设简介,请点击下方生成AI简介按钮。
介绍自己
生成预设简介
推荐相关文章
生成AI简介

过渡与动画

Vue 封装了过渡与动画效果

作用:插入更新移除 Dom 元素时,自动在合适的时刻在过渡标签添加移除不同的类名,只需写动画和过渡效果并应用到对应时刻的类名上,而无需手动操作 Dom

过渡标签:
(1) <transition> 包裹需要动画效果的单个元素
(2) <transition-group> 包裹需要动画效果的多个元素,每个元素都需要配置 Key 属性

不同时刻样式类名:
(1) 控制元素进入的样式

  1. v-enter 进入的起点
  2. v-enter-active 进入过程中
  3. v-enter-to 进入的终点

(2) 控制元素离开的样式

  1. v-leave 离开的起点
  2. v-leave-active 离开过程中
  3. v-leave-to 离开的终点

过渡标签添加 name 属性来配置类名的前缀,默认是 v,如进入起点的类名是 .v-enter<前缀>-enter

离开和进入:即元素的插入更新移除,通常配合 v-showv-if 来控制

添加 appear 属性让动画在网页首次加载时、元素首次插入时也触发

元素飞入飞出案例

分别用动画属性 animate过渡属性 transition 配合不同的类名实现相同的动画效果

模板结构:

1
2
3
4
5
6
7
8
<template>
<div>
<button @click="isShow=!isShow">显示隐藏</button>
<transition name="hello" appear>
<h1 v-show="isShow" class="title">你好</h1>
</transition>
</div>
</template>

交互:

1
2
3
4
5
6
7
8
export default {
name: 'Test-',
data(){
return{
isShow: true,
}
}
}

使用动画属性 animate 配合 .v-enter-active.v-leave-active

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.title {
background: rgb(114, 196, 219);
}
/* 进入过程的动画 */
.hello-enter-active{
animation: titleShow 1s;
}
/* 离开过程的动画 */
.hello-leave-active{
animation: titleShow 1s reverse;
}
/* 动画 */
@keyframes titleShow{
from {
transform: translateX(-100%);
}
to{
transform: translateX(0px);
}
}

过渡属性 transition 配合进入和离开的起点、终点的样式实现动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.title {
background: rgb(114, 196, 219);
}
/* 设置进入起点的样式 */
.hello-enter {
transform: translateX(-100%);
}
/* 设置进入终点的样式 */
.hello-enter-to {
transform: translateX(0);
}
/* 设置离开起点的样式 */
.hello-leave {
transform: translateX(0);
}
/* 设置离开终点的样式 */
.hello-leave-to {
transform: translateX(-100%);
}
/* 设置 transition 属性 */
.hello-enter-active, .hello-leave-active {
transition: 0.5s linear;
}

第三方动画库

有许多优秀的动画库,引入即可使用,以 animate.css 为例

安装:npm install animate.css --save

使用第三方库时,通常要在过渡标签上通过几个属性来自定义样式类名的后缀,name属性设置前缀
(1) enter-active-class 属性:设置进入过程中的样式类名
(2) leave-active-class 属性:设置离开过程中的样式类名

使用:引入动画库后,在过渡标签上设置name前缀以使用该动画库,然后在animate.css文档中挑选动画效果,将进入动画的类名设置到 enter-active-class 属性中,离开动画的类名设置到 leave-active-class 属性中,通过设置样式类名后缀来使用具体的动画效果

案例:

1
2
3
4
5
6
7
8
9
10
// 引入动画库
import 'animate.css'
export default {
name: 'Test-',
data() {
return {
isShow: true,
}
}
}

模板结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<button @click="isShow = !isShow">显示隐藏</button>
<!-- 设置动画 -->
<!-- name设置前缀表示使用animate.css动画库 -->
<!-- 通过设置样式类名后缀来使用具体的动画效果 -->
<transition
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__backOutUp"
appear
>
<h1 v-show="isShow" class="title" key="1">你好</h1>
</transition>
</div>
</template>

CSS 样式,因为使用了动画库,就无需自己写动画了

1
2
3
.title {
background: rgb(114, 196, 219);
}

ToDoList添加动画

给 ToDoList 案例中每个todo 的新增和删除添加动画

效果:

修改 ToDoList.vue 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
<div class="todo-list">
<ul>
<transition-group name="todo">
<ListItem v-for="item in todos" :key="item.id" :todo="item"></ListItem>
</transition-group>
</ul>
</div>
</template>

<!-- ...... -->

<style>
/* ........ */
/* 动画 */
.todo-enter,
.todo-leave-to {
opacity: 0;
transform: translateX(-50%);
}

.todo-enter-to,
.todo-leave {
opacity: 1;
transform: translateX(0);
}
.todo-enter-active, .todo-leave-active {
transition: all 0.3s;
}
</style>

Vue中发请求

在 Vue 中发请求通常用 Axios

安装: npm i axios

Axios 笔记: AJAX请求相关-Axios

Vue-cli配置代理

当后端没有配置 cors 时,本地开发环境请求后端API就会产生跨域问题

服务器之间通信没有跨域问题,可以在本地配置一个代理服务器去请求API

vue.config.js 中添加 devServer 配置项,以在开发环境下将 API 请求代理到 API 服务器

1
2
3
4
5
6
7
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: '<转发的url>'
}
})

配置代理后,将请求的 baseURL 改为本地ip+端口,如 120.0.0.1:8080,代理服务会将请求转发,自己去请求实际的API地址,然后返回数据

有些时候并不想所有发往自身获取资源的请求都被代理转发,实际想获取的是本地public文件夹下的资源,而不是远程API的

可以写完整版 devServer 配置,匹配路径去选择性代理

作用:可以配置多个代理,且可以灵活的控制发往本地的请求是否走代理转发

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
// 匹配路径代理
'/api': {
target: '<url>', // 代理目标的baseURL
ws: true, // 用于支持websocket
changeOrigin: true, // 伪造Host为代理目标baseURL
pathRewrite: {'<正则匹配路径>', '<替换内容>'} // 重写路径
},
'/foo': {
target: '<other_url>'
}
}
}
})

还是让后端配cors好

获取所有账单

在 NodeJS 中写过一个记账本案例,里面写了一套完整的 API,刚好拿来用

KeepingBook-API文档

功能:点击登陆提示登陆中,登陆成功提示成功登陆,点击获取账单,提示加载中,请求成功后展示所有账单的列表

App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<template>
<div>
<button @click="login">登录获取token</button>
<button @click="getData">获取所有账单</button>
<!-- 提示 -->
<div v-show="tip !== ''" class="tip">{{ tip }}</div>
<ul>
<li v-for="(item, index) in kpb" :key="item.id">
{{ index + 1 }}: {{ item.matter }} | {{ item.date }} | {{ item.type }} | {{ item.account }}
</li>
</ul>
</div>
</template>

<script>
import axios from "axios";
axios.defaults.baseURL = 'https://kpb.qcqx.cn';
export default {
name: "App",
data() {
return {
// 登陆返回的token
token: "",
// 账单数据
kpb: "",
// 提示
tip: "欢迎,请登陆",
}
},
methods: {
// 登陆
login() {
this.kpb = "";
this.tip = "登陆中....";
axios({
url: '/api/login',
method: 'post',
data: {
username: 'qx',
password: '123'
},
// 请求超时
timeout: 5000
}).then(res => {
// 响应体对象
console.log(res.data);
this.token = res.data.data.token;
this.tip = "登陆成功";
}).catch(err => {
console.log(err);
this.tip = "登陆失败";
});
},
// 获取账单
getData() {
this.kpb = "";
this.tip = "账单加载中....";
axios({
url: '/api',
method: 'get',
headers: {
token: this.token
},
// 请求超时
timeout: 5000
}).then(res => {
// 响应体对象
console.log(res.data);
if (res.data.data === null) {
this.tip = res.data.msg;
return;
}
this.kpb = res.data.data;
this.tip = "";
}).catch(err => {
console.log(err);
this.tip = "获取账单失败";
});
}
}
};
</script>

插槽

插槽是由子组件在模板的合适位置通过 <slot> 定义的

作用:让父组件可以向子组件定义的插槽处插入 html 结构

插槽的种类:
(1) 默认插槽:简单地将组件标签中所有html结构放到插槽处
(2) 具名插槽:通过 <slot> 上的 name 属性区分插槽,通过 v-slot:<插槽名> 将html插入到指定插槽
(3) 作用域插槽:用于数据在子组件中,且不将数据外传,根据数据生成的结构由父组件决定的情况

注意:
(1) 父组件中要插入插槽的html结构也是在父组件中完成模板解析的,可以访问父组件中的数据,而不能直接访问到自组件的数据
(2) 三种插槽可以混合使用

默认插槽

简单地将组件标签中所有html结构放到插槽处

父组件
1
2
3
4
5
<ListBox>
<ul>
<li v-for="(item, index) in arr" :key="index">{{ item }}</li>
</ul>
</ListBox>
子组件
1
2
<!-- 定义插槽 -->
<slot></slot>

具名插槽

通过 <slot> 上的 name 属性区分插槽,通过 v-slot:<插槽名> 将html插入到指定插槽

v-slot: 可以简写为 #

父组件
1
2
3
4
5
6
7
8
9
10
<ListBox>
<template v-slot:list>
<ul><li v-for="(item, index) in arr" :key="index">{{ item }}</li></ul>
</template>
<!-- v-slot: 简写为 # -->
<template #other>
<h2>chuckle</h2>
</template>
</ListBox>

子组件
1
2
<slot name="list"></slot>
<slot name="other"></slot>

作用域插槽

用于数据在子组件中,且不将数据外传,根据数据生成的结构由父组件决定的情况

子组件通过 <slot> 的标签属性传数据给父组件(只能在组件标签中使用)
父组件通过 #<插槽名>="obj" 的 obj 接收一个对象,对象中有传过来的属性名和属性值(数据)

父组件
1
2
3
4
5
6
7
8
9
10
11
<ListBox>
<!-- default代表无名插槽 -->
<template #default="{arr}">
<ul><li v-for="(item, index) in arr" :key="index">{{ item }}</li></ul>
</template>
<!-- v-slot接收到的是一个对象 -->
<template #other="obj">
<div>{{ obj.x }} | {{ obj.y }}</div>
</template>
</ListBox>

子组件
1
2
3
4
<!-- 将子组件的数据传给父组件内的组件标签中使用 -->
<slot :arr="arr"></slot>
<!-- 传给父组件多个数据 -->
<slot name="other" :x="x" :y="y"></slot>

Vuex

在实现组件间通信时,无论是全局事件总线还是消息订阅与发布,大量的声明事件或消息名,会让代码变得臃肿、难以维护

Vuex 是实现集中式状态(数据)管理的一个 Vue 插件,对 Vue 应用中多个组件的共享状态进行集中式的管理(读/写)

安装: npm install vuex --save Vue2 只能使用 Vuex3

功能:将原本某一组件管理的数据拿出来给 Vuex 管理,所有组件都能看到 Vuex 中管理数据的仓库 Store,以及使用仓库所提供的,对数据读和写的方法

何时用 Vuex 管理状态(数据):
(1) 多个组件依赖于同一状态
(2) 来自不同组件的行为需要变更同一状态

Vuex工作原理

Vuex 工作原理图:

Vuex 有三个重要组成部分,这三个部分都在 Store 实例上,本质都是对象

  1. Actions:进行一些业务逻辑(异步)的操作,如发送 AJAX 请求,不直接对数据进行操作
  2. Mutations:对数据进行直接的维护,有许多对数据进行操作的自定义方法
  3. State:状态(数据),存放着多个组件共享的数据

Vuex的工作循环:

  1. 组件通过 dispatch() 调用 Actions 中的方法,触发一些业务逻辑
  2. Actions 中业务逻辑处理完后,在合适时机调用 commit() 触发 Mutations 中对数据进行直接操作的方法
  3. 然后 State 中数据响应式地变化,触发对应视图更新

注意:如果对数据的操作不带有更多的业务逻辑,组件也可以直接调用 commit() 方法

Store:Vuex.Store() 构造函数创建,提供了三个重要组成部分以及 dispatch()commit() 等各种API

搭建Vuex环境

新建一个JS文件,用于配置和创建 Store 实例,通常是 src/store/index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vue from 'vue';
import Vuex from 'vuex';
// 使用vuex插件
Vue.use(Vuex);

// 创建三个重要组成部分
const actions = {}
const mutations = {}
const state = {}

// 创建store实例,并暴露出去
export default new Vuex.Store({
// 将三个重要部分都交给store管理
actions,
mutations,
state
});

然后在 new Vue() 时将 Store 实例作为配置项传入

目的:让 vm 和 vc 身上新增一个 $store 属性,让所有组件都能访问到数据仓库 store

main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import Vue from "vue";
import App from "./App.vue";
// 引入store实例
import store from "./store";

Vue.config.productionTip = false;

new Vue({
el: "#app",
// 使用store
store,
render: h => h(App),
})

纯Vue求和案例

App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<CountNum></CountNum>
</div>
</template>

<script>
import CountNum from "./components/CountNum.vue";
export default {
name: "App",
components: {
CountNum,
}
};
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<template>
<div>
<h3>{{ sum }}</h3>
<select v-model.number="num">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">+</button>
<button @click="reduce">-</button>
<button @click="addOdd">当前总和是奇数再加</button>
<button @click="addWait">延迟1s再加</button>
</div>
</template>

<script>
export default {
name: "CountNum",
data() {
return {
// 总和
sum: 0,
// 选择的数字
num: 0,
}
},
methods: {
// 加
add() {
this.sum += this.num;
},
// 减
reduce(){
this.sum -= this.num;
},
// 当前总和是奇数再加
addOdd(){
if(this.sum%2){
this.sum += this.num;
}
},
// 延迟1s再加
addWait(){
setTimeout(()=>{
this.sum += this.num;
}, 1000)
}
},
}
</script>

Vuex版求和案例

对纯 Vue 版进行修改,将 sum 交给 vuex 的 store 管理,将直接对数据的操作放到 Mutations 中,将带有业务逻辑的操作放到 Actions 中

一些总结与注意:

  1. 虽然 $store.state.xxx = xxx 直接修改数据,也能响应式更新视图,但这样做无法被 vuex-tools 所监视,所以不要直接修改数据
  2. commit()dispatch() 都只能传入两个参数,第一个是要触发的函数名,第二个是传入的数据
  3. actions 中的函数收到两个参数,第一个 context 指上下文,是一个 mini 的 store,有部分 store 上的属性和方法,第二个 valuedispatch() 传来的数据
  4. mutations 中的函数也收到两个参数,第一个 state 是 store 中的数据,第二个 valuecommit() 传来的数据
CountNum.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template>
<div>
<!-- 通过vc身上的$store.state获取数据 -->
<h3>{{ $store.state.sum }}</h3>
<select v-model.number="num">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">+</button>
<button @click="reduce">-</button>
<button @click="addOdd">当前总和是奇数再加</button>
<button @click="addWait">延迟1s再加</button>
<button @click="$store.state.sum = 1">测试直接修改数据</button>
</div>
</template>
<script>
export default {
name: "CountNum",
data() {
return {
// 选择的数字
num: 0,
}
},
methods: {
// 加
add() {
// 传入函数名去匹配对数据的操作和选择的数字
this.$store.commit('add', this.num)
},
// 减
reduce(){
this.$store.commit('reduce', this.num)
},
// 当前总和是奇数再加
addOdd(){
this.$store.dispatch('addOdd', this.num)
},
// 延迟1s再加
addWait(){
this.$store.dispatch('addWait', this.num)
}
},
}
</script>

/store/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import Vue from 'vue';
import Vuex from 'vuex';
// 使用vuex插件
Vue.use(Vuex);

// 有业务逻辑的操作放在actions中
const actions = {
// context:上下文,一个mini都store,有store中的部分属性和方法
// value,组件中dispatch()传过来的值
addOdd(context, value) {
if (context.state.sum % 2) {
// 业务逻辑处理完后调用上下文中的commit()
context.commit('add', value);
}
},
addWait(context, value) {
setTimeout(() => {
context.commit('add', value);
}, 1000)
}
}

// 没有业务逻辑的操作放在mutations中
const mutations = {
// mutations中的函数收到两个参数
// state:store中的数据,value:commit()传过来的值
add(state, value) {
state.sum += value;
},
reduce(state, value) {
state.sum -= value;
},
}

const state = {
// 数据
sum: 0,
}

// 创建store实例
export default new Vuex.Store({
actions,
mutations,
state
});

getters配置项

除了三个重要组成部分必须作为 Store 的配置项之外,还有其它配置项

getters 和计算属性差不多,对数据进行加工后再返回,其中的函数收到一个参数 state

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 准备getters
const getters = {
// 对sum进行放大10倍
bigSum(state){
return state.sum * 10;
}
}
export default new Vuex.Store({
actions,
mutations,
state,
// 配置getters
getters
});

通过 $store.getters 获取加工后的数据

1
2
<h3>{{ $store.state.sum }}</h3>
<h3>{{ $store.getters.bigSum }}</h3>

mapState和mapGetters

当一个组件需要获取多个状态时,总在模板中用 $store.state.xxx 获取状态,代码重复且冗余

即使是手动写成计算属性,也要重复去 return $store.state.xxx

mapState()mapGetters() 可以帮我们生成状态的计算属性,以此简洁地使用状态

需要引入后才能使用:

1
import { mapState, mapGetters} from 'vuex'

使用注意:

  1. 传入一个对象,key-value 是 <生成的计算属性名>:<状态名或getter名>
  2. 返回值是包含多个计算属性的对象,需要用 ... 对象展开运算符,将其与组件的计算属性对象合并
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 
import { mapState, mapGetters} from 'vuex'
export default {
/* .... */
computed: {
test(){
return 'test'
},
// 对象展开运算符
...mapState({
sum: 'sum'
}),
...mapGetters({
bigSum: 'bigSum'
})
},
/* .... */
}

当要生成的计算属性名状态名或getter名一样时,可以使用数组简写形式,传入数组,元素是状态名或getter名

1
mapState(['sum'])

mapActions和mapMutations

在 methods 中也写了很多看起来重复的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 加
add() {
// 传入函数名去匹配对数据的操作和选择的数字
this.$store.commit('add', this.num)
},
// 减
reduce(){
this.$store.commit('reduce', this.num)
},
// 当前总和是奇数再加
addOdd(){
this.$store.dispatch('addOdd', this.num)
},
// 延迟1s再加
addWait(){
this.$store.dispatch('addWait', this.num)
}

mapActions()mapMutations() 能够生成调用 commit 和 dispatch 方法的方法

用法和 mapState 和 mapGetters 差不多

1
2
3
4
5
6
7
methods: {
...mapMutations(['add', 'reduce']),
...mapActions({
addOdd: 'addOdd',
addWait: 'addWait'
}),
},

生成的方法长这样,需要传入一个value

1
2
3
add(value){
this.$store.commit('add', value)
}

所以调用时就需要手动传入 value

1
2
3
4
5
<!-- 手动传入加数num -->
<button @click="add(num)">+</button>
<button @click="reduce(num)">-</button>
<button @click="addOdd(num)">当前总和是奇数再加</button>
<button @click="addWait(num)">延迟1s再加</button>

Vuex模块化

不同的功能会用到不同的数据,当很多实现不同功能的数据都写在一个 index.js 中或一个配置项中时,会导致命名冲突且代码不易维护

作用:让代码更好维护,让多种数据分类更加明确

将不同数据的 store 配置项单独拿出,每个模块的函数获取的数据或上下文都是模块自己的,无需再指定,即模块的局部状态

/store/count.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
export default {
// 开启命名空间
namespaced: true,

actions: {
// context:上下文,一个mini都store,有store中的部分属性和方法
// value,组件中dispatch()传过来的值
addOdd(context, value) {
if (context.state.sum % 2) {
context.commit('add', value);
}
},
addWait(context, value) {
setTimeout(() => {
context.commit('add', value);
}, 1000)
}
},

mutations: {
// mutations中的函数收到两个参数
// state:store中的数据,value:commit()传过来的值
add(state, value) {
state.sum += value;
},
reduce(state, value) {
state.sum -= value;
},
},

state: {
sum: 0,
},

getters: {
bigSum(state) {
return state.sum * 10;
}
}
}

通过 Store()modules 配置项使用模块

/store/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue';
import Vuex from 'vuex';
// 使用vuex插件
Vue.use(Vuex);

// 导入求和案例配置
import count from "./count.js";

// 创建store实例
export default new Vuex.Store({
modules: {
// 使用模块
count,
}
});

调整 mapState()mapGetters() 等的参数,指定是触发哪个模块的 actionsmutations

1
2
3
4
5
6
7
8
computed: {
...mapState('count',['sum']),
...mapGetters('count',['bigSum'])
},
methods: {
...mapMutations('count',['add', 'reduce']),
...mapActions('count',['addOdd', 'addWait']),
},

总结:
(1) 命名空间:默认情况下,模块内部的 action、mutation 和 getter 注册在全局命名空间,这样使得多个模块能够对同一个 mutation 或 action 作出响应。如果希望模块具有更高的封装度和复用性,可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

(2) 开启命名空间后:

  1. 组件中读取 state 数据
    1
    2
    3
    4
    // 方式一:直接读取
    this.$store.count.sum
    // 方式二:借助mapState
    ...mapState('count',['sum'])
  2. 组件中读取 getters 数据
    1
    2
    3
    4
    // 方式一:直接读取
    this.$store.getters['count/bigSum']
    // 方式二:借助mapGetters
    ...mapGetters('count',['bigSum'])
  3. 组件中调用 dispatch
    1
    2
    3
    4
    // 方式一:直接读取
    this.$store.dispatch('count/addOdd', value)
    // 方式二:借助mapActions
    ...mapActions('count',['addOdd', 'addWait']),
  4. 组件中调用 commit
    1
    2
    3
    4
    // 方式一:直接读取
    this.$store.commit('count/add', value)
    // 方式二:借助mapActions
    ...mapMutations('count',['add', 'reduce']),