浅析Vuex工作原理
Kotori Y 27 Posts

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

上图为Vuex的工作原理图,那么什么时候会需要用到Vuex呢?Vuex官网是这么说的:

  • 多个视图依赖于同一状态。
  • 来自不同视图的行为需要变更同一状态。

大致意思就是不同的组件需要通过不同的方式操作同一个数据,下面进行展开讲解。

State

state是Vuex的一个属性,类型为Object,是数据源存放地,对应于与一般Vue对象里面的data. 此外,state里面存放的数据是响应式的,若store(Vuex的实例化对象)中的数据发生改变,依赖这个数据的组件也会发生更新。

Actions

当组件需要操作state里的数据时,通过Vux提供的APIdispatch(), 其中需要传递两个参数,第一个为动作类型 (字符串,假设为”FooBar”), 其中Actions这个对象里面有一个名为“FooBar”的方法(函数),可以接收dispatch()的第二个参数。

Mutations

紧接着,上述Actions里的“FooBar”对应的函数调用commit()接口,和dispatch()类似,同样需要动作类型和传递的参数,而Mutations对象同样有一个同名的方法。该函数也有两个参数,第一个为state,另一个为传递的参数。

这么看,中间的Actions似乎有点多余,但存在这样的业务需求:如果传递的参数不是固定的,需要请求另一台服务器,这样就需要把Ajax请求写在Actions里,并包装成promise返回,在调用处用async await处理返回的数据。这也是Actions相较于Mutations的一个不同,即Actions可以发送异步请求。

Getters

Vuex也提供了类似于Vue中的计算属性的接口,使用比较简单,具体见下面的代码。

示例代码

下面是一个简单的例子

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
<template>
<div id="app">
<div>Number</div>
<div>Number: {{ number }} </div>
<div>Opposite Number: {{ oppositeNumber }} </div>
<input type="number" v-model="num">
<button @click="add">Add</button>
</div>
</template>

<script>
import {mapState, mapGetters} from "vuex"

export default {
name: 'Test',
data() {
return {
num: 0
}
},
methods: {
add() {
const params = {num: parseInt(this.num)}
this.$store.dispatch("add", params)
}
},
computed: {
...mapState(["number"]),
...mapGetters(["oppositeNumber"])
}
}

</script>

Vuex的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
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
state: {
number: 0
},

actions: {
async add(context, params) {

const sleep = (delay) => {
return new Promise(resolve => {
setTimeout(resolve, delay)
})
}

await sleep(params.num*1000) // 模拟异步

context.commit("ADD", params)
}
},

mutations: {
ADD(state, params) {
state.number += params.num
}
},

getters: {
oppositeNumber(state) {
return state.number * -1
}
},
})

根目录的main.js

1
2
3
4
5
6
7
8
9
10
11
12
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')

P.S.

此外Vuex还提供了modules属性用于封装不同业务逻辑的state、actions、mutations以及getters。后面应该会单独写一篇来讲解的。

参考资料

  1. Vuex官方文档

  2. 浅析Vuex及相关面试题答案-前端开发-Me的知乎文章

  3. 尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通-尚硅谷的哔哩哔哩视频

  • Post title:浅析Vuex工作原理
  • Post author:Kotori Y
  • Create time:2021-11-05 17:30
  • Post link:https://blog.iamkotori.com/2021/11/05/浅析Vuex工作原理/
  • Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
 Comments