返回 导航

Vue.js

hangge.com

Vue.js - 使用Vuex进行状态管理详解1(核心概念、基本用法)

作者:hangge | 2026-09-29 09:34
    在 Vue.js 中,组件的数据通常定义在 data 或 setup 中。当组件间需要通信时,可通过传递 props 或触发 emit 事件实现。然而,对于深度嵌套的组件,传递 props 会变得非常繁琐,并且不能实现数据全局共享。 为了更好地解决这些问题,Vue.js 官方提供了一个状态管理插件:Vuex。Vuex 是 Vue.js 应用程序的状态管理库,它可以从组件中提取共享状态,并将其放在全局单例中进行管理。这些共享状态依然是响应式的,因此当状态发生变化时,所有依赖该状态的组件都会自动更新。本文我将详细介绍 Vuex 的核心概念和基本用法。

一、基本介绍

1,什么是状态管理

(1)在开发中,应用程序需要处理各种各样的数据,这些数据需要保存在应用程序中的某一个位置。对这些数据的管理,我们就称为状态管理。

(2)实际上,Vue.js 组件内部的数据以单向数据流的形式进行管理。具体来说,Vue.js 组件的数据定义在 State(即 data 或 setup)中,在 View 层(即 template)使用 State 中的数据,View 层中会产生一些 Actions(比如单击事件),而这些 Actions 可能会修改 State 的数据。这就是以单向数据流的形式进行状态管理。

2,为什么需要 Vuex

(1)如今 JavaScript 开发的应用程序变得越来越复杂,需要管理的状态也越来越多。比如:
  • 服务器返回的数据、缓存数据、用户操作产生的数据等
  • UI 状态,比如元素是否被选中、是否显示加载动效等
  • 这些状态通常需要在多个组件之间共享

(2)如果还是通过 Props 传递或 Provide/Inject 等方式来共享这些复杂且需要在多个组件中共享的数据,状态就会变得非常难以控制和追踪,也难以实现在兄弟组件之间共享数据。比如:状态之间相互存在依赖、一个状态的变化会引起另一个状态的变化、状态需要在多个组件之间共享等。

(3)因此,我们可以考虑将组件内部状态抽离出来,以一个全局单例的方式进行管理。这样,我们可以通过插件的形式将该单例挂载到 Vue.js 3 实例上,任何组件都能从该单例上获取状态或触发行为。这种方式能够更好地控制和追踪状态的变化,同时能够更好地实现兄弟组件之间共享数据。这就是 Vuex 背后的基本思想。

3,Vuex 核心概念

(1)Vuex 主要由以下几个核心概念组成:
  • state:即存储数据的地方,所有组件都可以访问和使用 store 中的状态。
  • getters:可以理解为 store 中的计算属性,用于从 store 中的 state 中派生一些状态。 
  • mutations:用于同步修改 store 中的状态,必须是同步函数。 
  • actions:用于异步提交 mutations,可以包含任意异步操作。 
  • modules:用于将 store 分割成多个模块,每个模块可以维护自己的 state、getter、mutation、 action. 

(2)整个数据流程如下:
  • (1)在 State 中定义全局状态。
  • (2)在 Vue Components 组件树中使用 State 定义的状态。
  • (3)组件通过 Dispatch 分发 Actions(也可直接通过 Commit 提交到 Mutations)。
  • (4)Actions 支持编写异步逻辑,可将异步请求的数据提交到 Mutations 中。
  • (5)Mutations 以同步的方式修改 State 状态。
提示:Mutations 中的函数必须是同步的,这是为了能够让 Vue Devtools 追踪状态的变化。如果需要进行异步操作,应该在 Actions 中处理。

4,关于 Pinia

(1)对于 Vue 3 项目,官方推荐使用 Pinia 作为状态管理库。Pinia 的体积更小(约 1KB),语法更简洁,与 Composition API 结合更紧密,且提供更好的 TypeScript 支持。

(2)Pinia 没有 mutations,只有 state、getters 和 actions,可以直接修改 state。新项目其实更建议优先考虑 Pinia。

二、安装配置

1,安装 Vuex

(1)首先,我们需要在项目中安装 Vuex 4(专为 Vue.js 3 设计的版本)。打开终端,执行如下命令:
注意:Vuex 4 是与 Vue 3 匹配的版本。Vuex 3 是与 Vue 2 匹配的版本。如果你的项目已经深度绑定 Vuex 且没有迁移计划,本文介绍的方法仍然适用。
npm install vuex@4 --save

(2)或者执行如下命令安装最新版本:
提示:建议安装指定版本 vuex@4,以确保与 Vue.js 3 的兼容性。
npm install vuex@next --save

2,创建 Store

(1)在 Vue.js 3 中,Vuex 的核心是 Store(仓库)。仓库本质上是一个容器,用于存储应用程序大部分的状态。仓库中存储的状态具有以下特点:
  • 响应式:当组件从仓库中读取状态时,如果仓库中的状态发生变化,那么相应的组件也会更新。
  • 不可直接修改:改变仓库中状态的唯一途径是显式提交 mutation。

(2)下面我们创建第一个仓库。在项目的 src 目录下新建一个 store 文件夹,接着在该目录下新建 index.js 文件,具体代码如下。代码主要实现了三个功能:
  • 从 vuex 中导入 createStore 函数,该函数用于创建 store 对象。
  • 调用 createStore 函数创建 store 对象,并在该函数的对象参数中定义一个 state 函数。该函数需要返回一个对象,在该对象中定义一个全局变量 counter,并赋值为 0。
  • 默认导出 store 对象。
import { createStore } from 'vuex'

// 创建 store 对象
const store = createStore({
  // 定义全局共享的状态
  state() {
    return {
      counter: 0
    }
  }
})

export default store

3,挂载到 Vue 实例

    安装 Vuex 插件和安装 Vue Router 插件类似。修改 src/main.js 入口文件,先导入 store 对象,然后调用 app.use() 函数来安装 Vuex 插件。安装完成后,所有组件都可以通过 this.$store 访问全局状态。
import { createApp } from 'vue'
import App from './App.vue'
import store from './store/index'
const app = createApp(App)
// 安装 Vuex 插件
app.use(store)
app.mount('#app')
    

三、基本使用

1,读取状态

(1)修改 src/App.vue 组件,直接在模板中使用 $store.state 来访问 counter 变量:
<template>
  <div>
    当前计数: {{ $store.state.counter }}
  </div>
</template>

(2)保存代码,在终端执行 npm run serve,运行效果如下:

2,修改状态

(1)修改 store 中的变量必须在 mutations 中进行。我们修改 store/index.js 文件,在 createStore 函数的对象类型参数中添加了 mutations 属性,并在该属性中定义 increment 和 decrement 两个函数来修改全局的 counter 变量。
注意:在 mutations 中定义的函数,第一个参数默认会获取 state() 函数中返回的对象。
import { createStore } from 'vuex'

const store = createStore({
  // 1. 定义全局共享的状态
  state() {
    return {
      counter: 0
    }
  },
  // 2. 在 mutations 中修改全局状态
  mutations: {
    // 定义 increment 函数,参数 state 是 state() 函数返回的对象
    increment(state) {
      state.counter++
    },
    decrement(state) {
      state.counter--
    }
  }
})

export default store

(2)接下来需要通过 commit 函数触发执行 mutations 中定义的函数。修改 src/App.vue 组件,在模板中添加了两个 <button> 按钮,分别用于实现计数器的加 1 和减 1 操作。当单击按钮时,通过 this.$store.commit() 触发 mutations 中对应函数的调用。
<template>
  <div>当前计数: {{ $store.state.counter }}</div>
  <button @click="increment">+1</button>
  <button @click="decrement">-1</button>
</template>

<script>
export default {
  name: 'App',
  methods: {
    increment() {
      // Options API 语法:通过 this.$store.commit 触发 mutations
      this.$store.commit('increment')
    },
    decrement() {
      this.$store.commit('decrement')
    }
  }
}
</script>
(3)运行效果如下: 

4,使用 Composition API

(1)在 Vue.js 3 的 Composition API 中,我们可以使用 useStore 来获取 store 对象:
提示:在 setup() 函数中不能使用 this,因此需要调用 useStore() 函数获取全局 store 对象。这与在选项式 API 中访问 this.$store 是等效的。
<template>
  <div>当前计数: {{ $store.state.counter }}</div>
  <button @click="increment">+1</button>
  <button @click="decrement">-1</button>
</template>

<script>
import { useStore } from 'vuex'

export default {
  name: 'App',
  setup() {
    // 获取全局 store 对象
    const store = useStore()

    const increment = () => {
      // Composition API 语法:通过 store.commit 触发 mutations
      store.commit('increment')
    }

    const decrement = () => {
      store.commit('decrement')
    }

    return {
      increment,
      decrement
    }
  }
}
</script>

(2)运行效果同上面是一样的:

附一:Vue.js devtools 插件安装

1,插件介绍

(1)Vue.js devtools 是一款 Vue.js 的开发者工具,用于帮助开发人员调试和检查 Vue.js 应用。它允许开发人员查看组件的结构、状态和数据流,支持实时调试和修改组件状态,以及捕获和分析 Vue.js 应用的性能。

(2)使用 Vuex 时,Vue.js devtools 可以帮助我们追踪 mutations 的调用历史和状态变化,非常方便调试。该工具安装方式可以参考我之前写的文章:

2,插件使用

    重新启动浏览器和 Vue.js 项目,打开控制台并选择 Vue 选项卡。这样就可以正常使用 Vue.js devtools 来调试组件或 Vuex 了。例如,我们可以在 Vue.js devtools 中查看 Vuex 中存储的 counter 状态。 
评论

全部评论(0)

回到顶部