Vuex(状态管理)
Vuex的安装和配置、Vuex的基本使用(State、Mutation、Action、Getter)
# Vuex 的安装和配置
Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享
(1). 安装 Vuex 依赖包:npm install vuex@3.6.2 -S
(2). 在 项目下 新建 store/index.js 文件
// store/index.js 文件
import Vue from 'vue'
// 1. 导入 vuex
import Vuex from 'vuex'
Vue.use(Vuex)
// 2. 创建 store 实例对象(数据源)
export default new Vuex.Store({
// (1) state:定义全局的数据(数据保存在内存中,可以在浏览器本地查看到)
state: {
count: 0,
},
// (2) mutations:定义全局的方法(用于修改 state 中的数据)
mutations:{},
// (3) actions:定义全局"异步操作"的方法(如:发请求、计时器)
actions: {},
// (4) getters:定义全局"包装数据"的方法(用于对 state 中的数据进行包装)
getters: {},
})
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
(3). 在 main.js 入口文件中,挂载 store 对象
// main.js 入口文件
import store from './store'
new Vue({
router,
// 将 store 对象,挂载到 vue 实例中
// 所有的组件,可以直接获取到 store 中定义的全局数据、全局方法、等
store,
render: h => h(App)
}).$mount('#app')
2
3
4
5
6
7
8
9
10
(4). 组件中获取全局数据
<template>
<div>
<!-- 组件中获取 state 中的全局数据 -->
<h1>{{ $store.state.count }}</h1>
</div>
</template>
2
3
4
5
6
# 1. State 的使用(全局数据)
State 提供唯一的公共数据源,所有的共享数据都要放到 state 中进行存储
1. 在 store 实例对象中,定义 state 节点(用于定义全局数据)
// store/index.js 文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 创建 store 实例对象(数据源)
export default new Vuex.Store({
// state:定义全局数据(数据保存在内存中,可以在浏览器本地查看到)
state: {
count: 0,
},
})
2
3
4
5
6
7
8
9
10
11
12
13
2. 在组件中获取 state 中的数据:有两种方式
<template>
<div>
<!-- 方式1:组件中获取 state 中的全局数据 -->
<h1>{{ $store.state.count }}</h1>
<!-- 方式2:组件中获取 state 中的全局数据 -->
<h1>{{ count }}</h1>
</div>
</template>
<script>
// 2-1 按需导入 mapState 函数
import { mapState } from 'vuex'
export default {
// 2-2 使用 mapState 函数,将全局数据,映射为当前组件的计算属性
computed: {
// 将 count 全局数据,映射为当前组件的计算属性(在模板中直接渲染)
...mapState(["count"])
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
注意:不建议在组件中直接修改 state 中的数据,建议通过 mutation 来修改 state 中的数据
# 2. Mutations 的使用(全局方法)
Mutations 用于变更 state 中的数据
1. 在 store 实例对象中,定义 Mutations 节点(用于修改 state 中的数据)
// store/index.js 文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
num: 10
},
// mutations:定义全局方法(用于修改 state 中的数据)
mutations:{
// 定义方法(且第一个参数必须为 state 对象)
add(state) {
state.count++ // 让count值自增
},
setNum(state, newNum) {
state.num = newNum // 接收一个参数,赋值给num
}
},
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2. 在组件中调用 mutations 中的方法:有两种方式
<template>
<div>
<h1>当前值为:{{ $store.state.count }}</h1>
<button @click="change">+1</button>
<h2>{{ $store.state.num }}</h2>
</div>
</template>
<script>
// 按需导入 mapMutation 函数
import { mapMutations } from 'vuex'
export default {
methods: {
change() {
// 方式1:使用 commit 来触发 mutations 中的 add方法
this.$store.commit("add")
// 触发 setNum 方法,并传入参数
this.$store.commit("setNum", 100)
},
// 方式2:使用 mapMutation 函数,将 add、setNum 全局方法,映射为当前组件的方法
...mapMutations(["add", "setNum"])
change() {
// 映射后的方法,直接调用(相当于组件自己的方法)
this.add()
this.setNum(200)
},
}
};
</script>
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
注意:mutations 节点下,不能进行异步操作(如:计时器、发请求)
# 3. Actions 的使用(异步操作)
Actions 用于处理异步操作
1. 在 store 实例对象中,定义 Actions 节点(用于用于处理异步操作)
// store/index.js 文件
export default new Vuex.Store({
state: {
count: 0,
},
// mutations:定义全局方法(用于修改 state 中的数据)
mutations:{
// 定义方法(且第一个参数必须为 state 对象)
addN(state, step) {
state.count += step
}
},
// actions:定义全局"异步操作"方法(如:计时器、axios请求)
actions: {
// 定义一个异步操作的方法
addAsync(context,num) { // 第一个参数必须为context
setTimeout(() => {
context.commit("addN", num) // 通过 commit 触发 mutations 中的 addN 方法,并传入参数
}, 1000)
},
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2. 在组件中调用 actions 中的异步方法:有两种方式
<script>
// 按需导入 mapActions 函数
import { mapActions } from 'vuex'
export default {
methods: {
change() {
// 方式1:使用 dispatch 来触发 actions 中的 addAsync 异步方法,并传入参数
this.$store.dispatch("addAsync", 5)
},
// 方式2:使用 mapActions 函数,将 addAsync 全局异步方法,映射为当前组件的异步方法
...mapActions(["addAsync"])
change() {
// 映射后的方法,直接调用(相当于组件自己的方法)并传入参数
this.addAsync(10)
},
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
注意:在 actions 中,不能直接修改 state 中的数据(需要通过 context.commit() 来触发 mutations 中的方法,间接变更数据)
# 4. Getters 的使用(包装数据)
Getters 用于包装 State 中的数据
1. 在 store 实例对象中,定义 Getters 节点(用于对 State 中的数据进行加工处理,形成新的数据,类似于计算属性)
// store/index.js 文件
export default new Vuex.Store({
state: {
count: 0,
},
// getters:定义全局"包装数据"的方法(用于对 state 中的数据进行包装)
getters: {
showNum(state) {
return "当前最新的值为" + state.count // 包装数据,并返回
},
// 也可以这样写
showNum: state => {
return "当前最新的值为" + state.count
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2. 在组件中获取 getters 中的方法返回的包装数据:有两种方式
<template>
<div>
<!-- 方式1:组件中获取 getters 中的方法返回的包装数据 -->
<h1>{{ $store.getters.showNum }}</h1>
<!-- 方式2 -->
<h1>{{ showNum }}</h1>
</div>
</template>
<script>
// 2-1 按需导入 mapGetters 函数
import { mapGetters } from 'vuex'
export default {
computed: {
// 2-2 将 getters 中的方法返回的包装数据,映射为当前组件的计算属性
...mapGetters(["showNum"]) // 模板中直接渲染
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
注意:Getters 不会修改 State 中的原数据,只起到包装数据的作用(State 中的数据发生变化时,Getters 中的数据也会跟着变化)
# 总结
总结:Vuex 的使用
1. 在 store/index.js 中,定义全局的数据和方法
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 1. state:定义全局的数据(数据保存在内存中,可以在浏览器本地查看到)
state: {
count: 0,
},
// 2. mutations:定义全局的方法(用于修改 state 中的数据)
mutations:{
// 第一个参数必须为 state 对象
add(state) {
state.count ++
},
addN(state, num) {
state.count += num
}
},
// 3. actions:定义全局"异步操作"的方法(如:发请求、计时器)
actions: {
// 第一个参数必须为context
addAsync(context,num) {
setTimeout(() => {
// 通过 commit 触发 mutations 中的 add 方法,并传入参数
context.commit("add", num)
}, 1000)
},
},
// 4. getters:定义全局"包装数据"的方法(用于对 state 中的数据进行包装)
getters: {
showNum: state => {
return "当前最新的值为" + state.count // 返回包装的数据
}
}
})
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
2. 在组件中,获取全局数据 和 调用全局方法
<template>
<div>
<!-- 【1】获取 state 中的数据 -->
<!-- 方法一:使用 $store.state.全局数据名称 直接渲染出 state 中的数据 -->
<h1>{{ $store.state.count }}</h1>
<!-- 方法二:使用 mapState 函数 -->
<h2>{{ count }}</h2>
<!-- 【2】 调用 mutations 中的方法 -->
<!-- 方法一:使用 commit 来触发 mutations 中的 add 方法 -->
<button @click="$store.commit('add')"></button>
<!-- 方法二:使用 mapMutations 函数 -->
<button @click="addN(5)"></button>
<!-- 【3】 调用 actions 中的方法 -->
<!-- 方法一:使用 dispatch 来触发 actions 中的 addAsync 方法 -->
<button @click="$store.dispatch('addAsync')"></button>
<!-- 方法二:使用 mapActions 函数 -->
<button @click="addAsync(5)"></button>
<!-- 【4】获取 getters 中的方法返回的包装数据 -->
<!-- 方法一:使用 $store.getters.包装数据方法名 直接渲染返回的包装数据 -->
<h1>{{ $store.getters.showNum }}</h1>
<!-- 方法二:使用 mapGetters 函数 -->
<h2>{{ showNum }}</h2>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
export default {
computed: {
// mapState 函数:将 state 中的 count 数据,映射为当前组件的计算属性
...mapState(["count"]) // 模板中直接渲染
// mapGetters 函数: 将 getters 中的方法返回的包装数据,映射为当前组件的计算属性
...mapGetters(["showNum"]) // 模板中直接渲染
},
methods: {
// mapMutations 函数:将 mutations 中的 addN 方法,映射为当前组件的方法
...mapMutations(["addN"]) // 模板中直接调用并传参
// mapActions 函数:将 actions 中的 addAsync 异步方法,映射为当前组件的异步方法
...mapActions(["addAsync"]) // 模板中直接调用并传参
}
};
</script>
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