Vuex

vuex简介

Vuex 是 Vue.js 官方提供的用于状态管理的库。它主要用于解决 Vue.js 应用中多个组件之间的状态共享和数据传递问题,比如网站中登录中的cookietoken信息。vuex官网:https://vuex.vuejs.org/zh/

状态管理

什么是“状态管理模式”?让我们从一个简单的 Vue 计数应用开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Counter = {
// 状态
data () {
return {
count: 0
}
},
// 视图
template: `
<div>{{ count }}</div>
`,
// 操作
methods: {
increment () {
this.count++
}
}
}

createApp(Counter).mount('#app')

这个状态自管理应用包含以下几个部分:

  • 状态,驱动应用的数据源;
  • 视图,以声明方式将状态映射到视图;
  • 操作,响应在视图上的用户输入导致的状态变化。

对于单个组件这种管理没有什么问题,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

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

对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。

安装

直接下载 / CDN 引用

在 Vue 之后引入 vuex 会进行自动安装:

<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>

npm安装

npm install vuex@next --save

Vuex 关键概念

  1. State(状态): Vuex 中的状态类似于组件中的 data,是存储数据的地方。状态是响应式的,因此当状态发生变化时,相关组件会自动更新。

  2. Mutations(变更): Mutations 是用于修改状态的函数。它们必须是同步函数,用于同步地改变状态。通过提交(commit)一个 Mutation,你可以修改状态。

  3. Actions(动作): Actions 用于处理异步操作,例如发起网络请求或执行一系列的 Mutations。Actions 可以包含异步代码,然后通过提交 Mutations 来修改状态。

  4. Getters(获取器): Getters 允许你从状态中派生出一些新的状态,类似于 Vue 组件中的计算属性。它们对状态进行一些计算或转换。

  5. Modules(模块): Vuex 允许将 store 拆分为多个模块。每个模块有自己的 state、mutations、actions 等。这有助于组织大型应用的代码。

  6. Store(仓库): Store 是 Vuex 应用的中心化存储,包含了应用中的大部分状态。它是一个单一的对象,可以在所有组件中访问。

使用 Vuex 可以有效地管理应用的状态,实现了组件之间的通信和协作,使得大型应用更容易维护和扩展。

以下是一个简单的 Vuex 示例:

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
import { createStore } from 'vuex';

const store = createStore({
state: {
count: 0,
},
mutations: {
increment(state) {
state.count++;
},
},
actions: {
incrementAsync(context) {
setTimeout(() => {
context.commit('increment');
}, 1000);
},
},
getters: {
doubleCount(state) {
return state.count * 2;
},
},
});

export default store;

你可以在组件中通过 this.$store 来访问 store,例如 this.$store.state.count 可以获取状态,然后你可以通过提交 mutations 或分发 actions 来修改状态。

State

在 Vuex 中,state 是一个用于存储应用程序的全局状态的对象。它代表了应用程序的数据,可以在应用程序的任何组件中访问和操作。state 对象包含了应用程序中各种数据的属性和值。

以下是一个简单的示例,展示了一个包含两个属性的 Vuex state 对象:

1
2
3
4
5
6
const store = new Vuex.Store({
state: {
count: 0, // 一个用于存储计数器的值的属性
user: null, // 一个用于存储用户信息的属性
},
});

在这个示例中,state 包含了两个属性:countusercount 属性存储一个用于计数的整数值,user 属性存储用户信息的对象。这些属性的值可以在应用程序的任何组件中使用。

要在 Vue 组件中访问 Vuex 的 state,你可以使用 mapState 辅助函数或直接通过 this.$store.state 访问。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 使用 mapState 辅助函数
import { mapState } from 'vuex';

export default {
computed: {
...mapState(['count', 'user']),
},
};

// 或者直接通过 this.$store.state 访问
export default {
methods: {
someMethod() {
const count = this.$store.state.count;
const user = this.$store.state.user;
// 进行操作...
},
},
};

通过这些方式,你可以访问和操作 Vuex 中的全局状态。当 state 的数据发生变化时,任何依赖于它的组件都会自动更新以反映这些变化。这是 Vuex 的核心特性之一,它提供了一个集中式的状态管理机制,使得状态的管理和共享变得更加容易。

Mutation

Vuex 中的 mutation(变更)是一种用于修改状态的方法。它是一个包含两个参数的函数:

  1. state:当前的状态对象,代表你的应用程序的状态。
  2. payload:一个包含需要修改的状态信息的对象。Payload 是一个普通的 JavaScript 对象,可以包含一个或多个属性,这些属性会用来更新状态。

Mutation 通常用于同步修改状态,即在执行 mutation 时,状态会立即得到更新。这有助于确保状态变更是可追踪的和可调试的。

以下是一个示例,展示了如何定义和使用 Vuex 中的 mutation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
},
decrement(state) {
state.count--
},
add(state, amount) {
state.count += amount
}
}
})

// 在组件中触发 mutation
store.commit('increment') // 增加 count
store.commit('decrement') // 减少 count
store.commit('add', 5) // 增加 count 5 次

在上面的示例中,incrementdecrement mutation 没有 payload,它们只是简单地增加或减少 state.count。而 add mutation 使用了 payload,允许你指定增加的数量。

总之,mutations 在 Vuex 中用于同步地修改状态,可以在组件中使用 commit 方法来触发它们,实现对状态的修改。

Actions

在 Vuex 中,Action 是用于触发Mutation的函数,它可以包含任意异步操作、业务逻辑或者多个 Mutation 的操作。Actions 主要用来处理异步任务,比如发起一个网络请求、定时器操作、或其他需要一定时间完成的任务。

Actions 定义的方式与 Mutation 相似,你可以在 Vuex 的 actions 属性中创建它们。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
incrementAsync(context) {
setTimeout(() => {
context.commit('increment') // 调用 Mutation 来增加 count
}, 1000)
}
}
})

在这个示例中,我们定义了一个名为 incrementAsync 的 Action,它会在异步操作中调用 Mutation increment 来增加 count。你可以使用 context.commit 来触发 Mutation。

在组件中触发 Action 可以使用 dispatch 方法,例如:

1
2
// 在组件中触发 incrementAsync Action
this.$store.dispatch('incrementAsync')

这将触发名为 incrementAsync 的 Action,该 Action 将等待一秒后调用 Mutation 来增加 count

总之,Actions 在 Vuex 中用于管理异步操作,而 Mutations 用于同步操作,通过 Action 可以更好地控制应用的异步流程。

参考资料