Vuex - 在Vue.js中的集中状态管理
注意
本文针对的是Vue 2。现在已经有了Vue 3,建议使用它来开发Vue应用程序。
在页面之间发送和接收数据的常见解决方案包括通过URL、cookies和LocalStorage传递数据。虽然这些方法可以工作,但它们没有提供操作数据的标准,也不是与Vue.js响应式相协调的响应式数据源。
Vue.js的创建者尤雨溪开发了一个名为Vuex的工具,专门为Vue设计,允许在使用该框架构建的Web应用程序中进行集中状态管理。虽然不是唯一的数据管理工具,但它与Vue生态系统集成得最好。
Vuex是一个用于Vue.js应用程序的状态管理模式库。它为应用程序中的所有组件提供了一个集中的存储,并有规则确保状态只能以可预测的方式进行变更。
对于需要跨不同组件访问集中、响应式数据的中大型应用程序,特别推荐使用Vuex。
安装
通过CDN,将其放在vue之后:
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
使用NPM:
npm install vuex --save
使用Yarn:
yarn add vuex
在使用模块系统(如vue-cli中的webpack)时,需要通过Vue.use()
显式安装Vuex:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
Vuex的基本结构
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {},
getters: {},
});
state
state
是包含我们可以从不同组件访问的所有数据的对象。其内容应该只通过mutations
进行修改,以使其修改透明且可审计。
state: {
count: 0
}
mutations
在Vuex存储中更改状态的唯一方法是提交一个mutation
。这些函数执行修改并接收state
作为第一个参数。
mutations: {
increment (state) {
state.count++
}
不能直接调用Mutations,所以它们通过store.commit
执行:
store.commit('increment');
Mutations也可以接收数据作为第二个参数,可以是数字、字符串、数组等。
mutations: {
increment (state, amount) {
state.count += amount
}
}
store.commit('increment', 10);
一个重要的点是mutations是同步的,这意味着任何状态更改都必须立即完成,而不能通过异步事务(如数据库或API查询)进行。对于异步状态更改,使用actions
。
actions
actions
与mutations类似,除了两点不同:
- 它们通过
store.dispatch
分派 actions
不是直接变更状态,而是提交mutationactions
可以包含异步代码- 它们接收一个
context
对象作为第一个参数,该对象使我们能够访问state、mutations、actions和getters actions
可以在resolved后返回一个promise
假设我们想在查询某个API后增加计数器,我们可以这样做:
actions: {
asyncIncrement (context) {
return new Promise((resolve, reject) => {
fetch('someApiX').then(() => {
context.commit('increment')
resolve()
})
})
}
}
或使用async/await
:
actions: {
async asyncIncrement (context) {
await fetch('someApiX')
context.commit('increment')
}
}
像这样使用:
store
.dispatch('asyncIncrement')
.then(() => console.log('计数器已增加!'));
了解更多关于JavaScript Promises的信息。
getters
getters
用于从state
中检索已处理的信息。它们接收state
作为第一个参数。
假设我们在state
中有一个任务列表,我们可以创建一个getter,只返回已完成的任务:
state: {
tasks: [
{ id: 1, text: 'lorem ipsum', done: true },
{ id: 2, text: 'lorem ipsum', done: true },
{ id: 3, text: 'lorem ipsum', done: false },
{ id: 4, text: 'lorem ipsum', done: false },
{ id: 5, text: 'lorem ipsum', done: true },
]
},
getters: {
doneTasks (state) {
return state.tasks.filter(task => task.done)
}
}
像这样使用:
store.getters.doneTasks;
/*
[
{ id: 1, text: 'lorem ipsum', done: true },
{ id: 2, text: 'lorem ipsum', done: true },
{ id: 5, text: 'lorem ipsum', done: true },
]
*/
getters
还可以通过返回一个函数来接收数据。因此,我们可以通过getter这样检索特定的任务id
:
getters: {
taskById: (state) => (id) => {
return state.tasks.find(task => task.id === id)
}
}
像这样使用:
store.getters.taskById(2); // { id: 2, text: 'lorem ipsum', done: true }
通过这种方式,我们可以管理组件中可访问的数据,这些数据可以通过mutations
和actions
进行变更,并且可以通过getters
以处理后的形式进行查询。为我们的应用程序提供了一个标准的数据使用模式,使我们能够更快地进行扩展。