Skip to content

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之后:

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

使用NPM:

javascript
npm install vuex --save

使用Yarn:

javascript
yarn add vuex

在使用模块系统(如vue-cli中的webpack)时,需要通过Vue.use()显式安装Vuex:

javascript
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

Vuex的基本结构

javascript
const store = new Vuex.Store({
  state: {},
  mutations: {}, 
  actions: {},
  getters: {},
});

state

state是包含我们可以从不同组件访问的所有数据的对象。其内容应该只通过mutations进行修改,以使其修改透明且可审计。

javascript
state: {
  count: 0
}

mutations

在Vuex存储中更改状态的唯一方法是提交一个mutation。这些函数执行修改并接收state作为第一个参数。

javascript
mutations: {
  increment (state) {
    state.count++  
  }

不能直接调用Mutations,所以它们通过store.commit执行:

javascript
store.commit('increment');

Mutations也可以接收数据作为第二个参数,可以是数字、字符串、数组等。

javascript
mutations: {  
  increment (state, amount) {
    state.count += amount
  }
}
javascript
store.commit('increment', 10);

一个重要的点是mutations是同步的,这意味着任何状态更改都必须立即完成,而不能通过异步事务(如数据库或API查询)进行。对于异步状态更改,使用actions

actions

actions与mutations类似,除了两点不同:

  • 它们通过store.dispatch分派
  • actions不是直接变更状态,而是提交mutation
  • actions可以包含异步代码
  • 它们接收一个context对象作为第一个参数,该对象使我们能够访问state、mutations、actions和getters
  • actions可以在resolved后返回一个promise

假设我们想在查询某个API后增加计数器,我们可以这样做:

javascript
actions: {
  asyncIncrement (context) {
    return new Promise((resolve, reject) => {
      fetch('someApiX').then(() => {
        context.commit('increment')
        resolve()
      }) 
    })
  }
}

或使用async/await

javascript
actions: {
  async asyncIncrement (context) {
    await fetch('someApiX')
    context.commit('increment') 
  }
}

像这样使用:

javascript
store
  .dispatch('asyncIncrement')
  .then(() => console.log('计数器已增加!'));

了解更多关于JavaScript Promises的信息。

getters

getters用于从state中检索已处理的信息。它们接收state作为第一个参数。

假设我们在state中有一个任务列表,我们可以创建一个getter,只返回已完成的任务:

javascript
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)
  }  
}

像这样使用:

javascript
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

javascript
getters: {
  taskById: (state) => (id) => {
    return state.tasks.find(task => task.id === id)
  }
}

像这样使用:

javascript
store.getters.taskById(2); // { id: 2, text: 'lorem ipsum', done: true }

通过这种方式,我们可以管理组件中可访问的数据,这些数据可以通过mutationsactions进行变更,并且可以通过getters以处理后的形式进行查询。为我们的应用程序提供了一个标准的数据使用模式,使我们能够更快地进行扩展。