Vuex 基本使用
# Vuex 基本使用
# 1. 原理
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式和库。它充当了应用中所有组件的集中式存储,规则确保状态只能以可预测的方式进行变更。这也使得管理组件之间共享的状态更加容易。
适用版本
- Vue 2.x 对应 Vuex 3.x
- Vue 3.x 对应 Vuex 4.x
文档参考
- Vuex 官方中文文档:Vuex 中文文档 (opens new window)
核心概念:
- State:驱动应用的数据源。
- View:声明式地将 State 映射到视图。
- Actions:处理来自视图的用户输入引起的状态变化。
什么时候使用 Vuex:
当应用遇到多个组件共享状态时,Vuex 很有用:
- 多个视图依赖于同一个状态。
- 不同视图的行为需要改变同一个状态。
工作原理图:
- State:保存应用的数据。
- Getters:从 State 派生数据,类似于计算属性。
- Mutations:同步变更 State。
- Actions:处理异步操作,然后提交 Mutations。
# 2. 环境搭建
# 1. 安装 Vuex插件
首先需要在项目中安装 Vuex
。在项目的根目录下,使用 npm 安装 Vuex
:
npm install vuex@3 --save
或者使用 Yarn 安装:
yarn add vuex@3
# 2. 创建 Store 文件
1. 创建 store 文件:src/store/index.js
// 引入 Vue 核心库
import Vue from 'vue';
// 引入 Vuex
import Vuex from 'vuex';
// 应用 Vuex 插件
Vue.use(Vuex);
// 准备 actions 对象——响应组件中用户的动作
const actions = {};
// 准备 mutations 对象——修改 state 中的数据
const mutations = {};
// 准备 state 对象——保存具体的数据
const state = {};
// 创建并导出 store
export default new Vuex.Store({
actions,
mutations,
state
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2. 在 main.js
中集成 store:创建 Vue 实例时,传入 store
配置项。
import Vue from 'vue';
import App from './App.vue';
// 引入 store,因 index.js 为默认路径,可直接使用 ./store 进行引入
import store from './store';
new Vue({
el: '#app',
render: h => h(App),
store // 将 store 集成到 Vue 实例中
});
2
3
4
5
6
7
8
9
10
- 注意:在引入 store 时,因为
index.js
是默认的读取路径,所以直接使用import store from './store'
即可。
# 3. Vuex Store 实例的常用方法
在使用 Vuex 时,我们通过 Store
实例提供的方法来操作和访问应用的状态。下面是一些常用的 Store
实例方法及其参数说明:
# 1. store.state
作用:访问 Vuex 中的状态。
使用:
store.state
返回整个状态树,你可以通过属性访问器访问具体的状态。示例:
const count = store.state.count; // 获取状态中的 count 值
1
# 2. store.getters
作用:访问 Vuex 中的计算属性(getters)。
使用:通过
store.getters
获取定义的计算属性。示例:
const bigSum = store.getters.bigSum; // 获取计算属性 bigSum 的值
1
# 3. store.commit(type, payload)
作用:提交
mutations
,同步地修改state
。参数:
- type:要提交的
mutation
的名称(字符串)。 - payload:可选参数,附加的数据(任意类型)。
- type:要提交的
使用:
store.commit
用于同步操作,直接修改状态。示例:
store.commit('INCREMENT', 10); // 提交 INCREMENT mutation,并传递 payload 10
1
# 4. store.dispatch(type, payload)
作用:触发
actions
,用于处理异步操作。参数:
- type:要触发的
action
的名称(字符串)。 - payload:可选参数,附加的数据(任意类型)。
- type:要触发的
使用:
store.dispatch
用于异步操作或复杂业务逻辑。示例:
store.dispatch('asyncIncrement', 5); // 触发 asyncIncrement action,并传递 payload 5
1
# 5. 其他较少使用的方法
1.store.subscribe(handler)
作用:订阅
store
的mutation
,每当mutation
被触发时调用指定的回调函数。参数:
- handler:回调函数,接收两个参数:
- mutation:包含
type
和payload
的对象。 - state:变更后的状态树。
- mutation:包含
- handler:回调函数,接收两个参数:
使用:用于监听每次
mutation
触发的事件,通常用于记录日志或调试。示例:
store.subscribe((mutation, state) => { console.log(mutation.type); // 输出 mutation 的类型 console.log(mutation.payload); // 输出 mutation 的负载 });
1
2
3
4
2. store.subscribeAction(handler)
作用:订阅
store
的action
,每当action
被触发时调用指定的回调函数。参数:
- handler:回调函数,接收一个对象参数:
- action:包含
type
和payload
的对象。 - state:当前状态树。
- action:包含
- handler:回调函数,接收一个对象参数:
使用:用于监听每次
action
触发的事件,通常用于记录异步操作日志或调试。示例:
store.subscribeAction((action, state) => { console.log(action.type); // 输出 action 的类型 console.log(action.payload); // 输出 action 的负载 });
1
2
3
4
3. store.watch(getter, callback, [options])
作用:响应式地监听
getter
返回值的变化。参数:
- getter:一个函数,返回要观察的目标数据。
- callback:数据变化时调用的回调函数,接收两个参数:
- newValue:变化后的新值。
- oldValue:变化前的旧值。
- options:可选参数,配置项:
- deep:是否进行深度监听(布尔值)。
- immediate:是否立即触发回调(布尔值)。
使用:用于监听某个状态或计算属性的变化。
示例:
store.watch( (state) => state.count, // 监听 count 状态 (newValue, oldValue) => { console.log(`Count changed from ${oldValue} to ${newValue}`); } );
1
2
3
4
5
6
4. store.replaceState(state)
作用:替换
store
的根状态,仅用于状态的热重载。参数:
- state:新的状态对象,替换当前的根状态。
使用:通常用于状态热重载。
示例:
const newState = { count: 0, user: { name: 'Alice' } }; store.replaceState(newState); // 替换整个状态树
1
2
5. store.hotUpdate(newOptions)
作用:动态地热更新
store
的配置(mutations、actions、getters)。参数:
- newOptions:包含新的
mutations
、actions
、getters
的对象。
- newOptions:包含新的
使用:用于在开发环境下热重载
Vuex
模块。示例:
store.hotUpdate({ mutations: { SET_COUNT(state, payload) { state.count = payload; } } });
1
2
3
4
5
6
7
# 4. 基本概念
在 Vuex 中,State
、Mutations
和 Actions
是构成状态管理的三个核心概念。它们各自承担着不同的角色,共同实现了 Vue.js 应用的集中式状态管理。
# 1. State
State 是 Vuex 中用于存储应用状态的对象。它是整个应用数据的源头,所有需要共享的数据都应该放在 state
中。state
是一个响应式对象,当 state
中的数据发生变化时,依赖于它的组件会自动更新。
参数
- State 本身是一个对象,内部可以定义任意数量的属性,每个属性代表一类数据状态。
示例
const state = {
count: 0, // 用于计数的状态
user: { // 用户信息
name: 'Alice',
age: 25
},
todos: [ // 任务列表
{ id: 1, text: 'Learn Vuex', done: true },
{ id: 2, text: 'Practice JavaScript', done: false }
]
};
2
3
4
5
6
7
8
9
10
11
- 在这个示例中,
state
包含三个属性:count
是一个整数,用于计数;user
是一个对象,包含用户的基本信息;todos
是一个数组,包含任务列表。
提示
在组件中,我们可以使用 this.$store.state
可以访问 Vuex 中的状态。
# 2. Mutations
Mutations 是 Vuex 中用于修改 state
的唯一方式。每个 mutation
都是一个同步函数,它接收 state
作为第一个参数,通常还可以接收一个可选的 payload
(载荷)作为第二个参数。mutations
确保了状态变更的可追踪性和可调试性。
参数
- state:当前的
state
对象。 - payload:可选参数,用于传递附加数据,通常是一个对象或者单个值。
示例
const mutations = {
// 增加 count
INCREMENT(state, payload) {
state.count += payload.amount; // 修改 state 中的 count
},
// 更新用户信息
UPDATE_USER(state, payload) {
state.user.name = payload.name;
state.user.age = payload.age;
}
};
2
3
4
5
6
7
8
9
10
11
INCREMENT
是一个mutation
,用于增加count
的值,payload
是一个包含amount
属性的对象;UPDATE_USER
是另一个mutation
,用于更新用户信息。
提示
在组件中,我们可以使用 this.$store.commit
可以提交 mutations
来修改状态。
# 3. Actions
概念
Actions
是 Vuex 中用于处理异步操作和复杂业务逻辑的部分。在 Vuex 的架构中,actions
不能直接修改状态,而是通过提交 mutations
来实现状态的变更。这样设计的目的是为了确保状态变更的可预测性和可追踪性。Actions
通常用于执行一些异步任务,比如从服务器获取数据、提交数据,或者在一个动作中调用多个 mutations
。
参数
- context:
actions
函数的第一个参数是context
,它是一个拥有与store
实例相同方法和属性的对象。常用属性和方法包括:context.state
:等同于store.state
,用于访问当前的状态。context.getters
:等同于store.getters
,用于访问当前的getters
。context.commit
:等同于store.commit
,用于提交mutations
。context.dispatch
:等同于store.dispatch
,用于触发其他的actions
。
- payload:
actions
的第二个参数是可选的payload
,用于传递附加数据给actions
或者mutations
。
示例
const actions = {
// 异步增加 count
asyncIncrement({ commit }, payload) {
// 使用 setTimeout 模拟异步操作
setTimeout(() => {
// 提交 mutation 修改 state
commit('INCREMENT', payload); // 传递 payload 给 mutation
}, 1000);
},
// 获取用户信息
fetchUser({ commit }, userId) {
// 模拟异步 API 调用,返回一个 Promise
return new Promise((resolve, reject) => {
setTimeout(() => {
// 模拟成功获取用户数据
const user = { name: 'Bob', age: 30 }; // 模拟用户数据
commit('UPDATE_USER', user); // 提交 mutation 更新用户信息
resolve(user); // 解决 Promise,返回用户数据
}, 500);
});
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
asyncIncrement
:这个action
用于异步增加count
。通过setTimeout
模拟异步操作,在 1 秒后调用commit('INCREMENT', payload)
提交INCREMENT
mutation,以修改state.count
。fetchUser
:这个action
用于模拟从服务器获取用户信息。它返回一个 Promise,在模拟的异步操作完成后提交UPDATE_USER
mutation 以更新state.user
,并解决 Promise,返回获取到的用户数据。
提示
在组件中,我们可以使用 this.$store.dispatch
可以触发 actions
来处理异步操作。
# 5. 基本使用
在 Vuex 中,状态管理是通过定义 state
、mutations
、actions
和 getters
等组成部分来实现的。下面是用一个简单示例来演示如何使用 Vuex 管理应用状态。
# 1. 初始化vuex数据
在 Vuex 的 store/index.js
配置 actions
和 mutations
,下面是一个简单示例:
import Vue from 'vue'; // 引入 Vue 框架
import Vuex from 'vuex'; // 引入 Vuex 库
Vue.use(Vuex); // 将 Vuex 安装为 Vue 插件
// actions 对象,用于定义响应组件动作的方法
const actions = {
// 响应组件中的加法动作
jia(context, value) {
// 提交一个 mutation,触发状态变更
context.commit('JIA', value);
}
};
// mutations 对象,用于定义具体修改 state 的方法
const mutations = {
// 执行加法,变更 state 中的 sum 值
JIA(state, value) {
state.sum += value; // 修改 state 中的 sum
}
};
// 初始化 state 对象,存储应用的状态数据
const state = {
sum: 0 // 初始 sum 值
};
// 创建并导出 store,包含 state、actions 和 mutations
export default new Vuex.Store({
actions, // 注册 actions
mutations, // 注册 mutations
state // 注册 state
});
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
State:是存储应用数据的地方。在上面的例子中,
state
对象初始化了一个名为sum
的变量,初始值为0
。Actions:用于处理异步操作或者复杂的逻辑,最终提交
mutations
以修改state
。在上面的代码中,jia
方法用于接收来自组件的请求,并提交到JIA
mutation。Mutations:是唯一可以直接修改
state
的地方,通常同步执行。在示例中,JIA
mutation 修改了state.sum
的值。
# 2. 在组件中访问和修改状态
在 Vue 组件中,可以通过 $store
对象来访问和修改状态。
在组件中访问状态:使用
$store.state.sum
从 Vuex 中读取数据。在组件中修改状态:使用
$store.dispatch('actionName', payload)
触发 action,或者使用$store.commit('mutationName', payload)
直接提交 mutation。
注意
任何想要永久改变 state
的操作都需要通过 mutations
,以确保状态变更的可预测性和可调试性。
2.1 访问状态
<template>
<div>
<!-- 通过 $store.state 访问 sum -->
<p>当前的和:{{ sum }}</p>
</div>
</template>
<script>
export default {
computed: {
// 通过计算属性映射 state 中的 sum
sum() {
return this.$store.state.sum;
}
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 访问状态:通过计算属性
sum
,我们可以在模板中使用来显示 Vuex 中的状态。
2.2 修改状态
<template>
<div>
<!-- 通过事件调用 add 方法,向 store 派发动作 -->
<button @click="add(5)">加 5</button>
</div>
</template>
<script>
export default {
methods: {
// 通过 actions 修改 state
add(value) {
// 使用 dispatch 派发 actions 中的 jia 方法
this.$store.dispatch('jia', value);
},
// 直接使用 mutations 修改 state
increment(value) {
// 直接提交 mutation 来修改 state
this.$store.commit('JIA', value);
}
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
- 修改状态:通过
dispatch
方法可以触发actions
,间接调用mutations
来修改state
;也可以直接使用commit
方法提交mutations
修改state
。一般来说,dispatch
适用于有异步请求或者复杂逻辑的场景,而commit
适用于简单的同步操作。
备注
- 在组件中,如果没有复杂的异步操作,可以直接使用
commit
而不是dispatch
。 - 模板中使用 {{
$store.state.sum
}} 来显示状态时,无需使用this
。 - 通常,mutation 中的方法名使用大写以便于区分
actions
和mutations
# 6. Getters
getters
是 Vuex 提供的一种机制,类似于组件中的计算属性 computed
,用于从 state
中派生出状态。在 Vuex 中,getters
可以对 state
中的数据进行处理、筛选、格式化等操作,并将结果返回,以便在组件中使用。getters
是惰性的,只有在其依赖的 state
改变时,才会重新计算。
getters 是如何工作的?
getters
仅仅是从state
派生出新数据,并返回这个数据给组件使用。getters
的结果并不会存储在state
中,因此不会同步修改state
中的值。getters
提供了一种只读的方式来计算和获取state
数据,所有getters
的计算结果都是临时的,并不影响state
本身。
# 1. 定义 Getters
在 Vuex 的 store/index.js
中定义 getters
。getters
是一个对象,包含多个属性方法,每个方法接收 state
作为其第一个参数,可以用来读取和加工状态。getters
方法可以接收最多四个参数:
- state:当前模块的
state
,用于访问和读取状态。 - getters:当前模块的
getters
,可用于访问其他getters
。 - rootState:全局的
state
,用于在模块化store
中访问全局状态。 - rootGetters:全局的
getters
,用于在模块化store
中访问全局getters
。
注意:getters
方法中的参数是按顺序传入的,参数名并不重要,只要参数顺序保持不变,功能就不会受到影响。
import Vue from 'vue'; // 引入 Vue 框架
import Vuex from 'vuex'; // 引入 Vuex 库
Vue.use(Vuex); // 将 Vuex 安装为 Vue 插件
// 定义初始 state
const state = {
sum: 0 // 初始数据,存储计算的总和
};
// 定义 getters
const getters = {
// 定义一个计算属性 bigSum,用于对 state.sum 进行加工处理
bigSum(state) {
return state.sum * 10; // 返回 sum 的十倍
},
// 定义一个计算属性 doubleBigSum,使用其他 getters
doubleBigSum(state, getters) {
return getters.bigSum * 2; // 返回 bigSum 的两倍
}
};
// 创建并导出 Vuex Store 实例
export default new Vuex.Store({
state, // 注册 state
getters // 注册 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
27
state
:存储应用的状态数据。在这个例子中,state
中包含一个sum
属性。getters
:包含计算属性。bigSum
是一个计算属性,它根据state.sum
的值计算出一个新的值(sum
的十倍)。
# 2. 在组件中使用 Getters
组件可以通过计算属性来使用 Vuex 中的 getters
。你可以在组件的 computed
属性中定义计算属性,利用 $store.getters
访问 getters
,注意getters
返回的数据是根据当前 state
计算得出的,无需在调用时传递参数。
<template>
<div>
<!-- 使用插值语法显示 bigSum 的计算结果 -->
<p>Big Sum: {{ bigSum }}</p>
</div>
</template>
<script>
export default {
computed: {
// 使用 Vuex 的 getters 获取 bigSum 的值
bigSum() {
return this.$store.getters.bigSum; // 访问 Vuex 中的 bigSum 计算属性
}
}
};
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
computed
属性:在组件中,使用computed
定义一个名为bigSum
的计算属性。this.$store.getters.bigSum
:通过this.$store.getters
访问 Vuex 的getters
,获取bigSum
的值。
总结
- 作用:
getters
用于从state
中派生状态,便于组件获取加工后的数据。 - 使用场景:当需要对原始状态数据进行变换、过滤或处理时,可以使用
getters
,而不是在组件中直接处理state
数据。 - 性能优势:类似于计算属性,
getters
只在其依赖的state
发生变化时才会重新计算,避免了不必要的性能开销。