Vuex 是 Vue.js 中的状态管理模式,广泛应用于 Vue 2 和 Vue 3 中,其内部实现存在一些差异。
1. 什么是 Vuex ?
Vuex 是 Vue.js 官方提供的状态管理库,用于集中管理应用的所有组件的状态。主要是通过一种集中化的方式来管理共享状态,尤其适用于中大型应用,避免了复杂的组件间通信问题(如 props 和 events)。Vuex 基于 Flux 架构,使用了单向数据流。它能够确保状态的变化是可预测的,从而提高了代码的可维护性。
1.1 Vuex 的核心概念
- State:应用的状态,存储数据。
- Getters:计算属性,派发获取应用状态的逻辑。
- Mutations:同步修改状态的方法。
- Actions:包含异步操作修改状态的方法。
- Modules:模块化的 Vuex 状态管理,每个模块都有自己的 state、mutations、actions 和 getters。
2. Vuex 在 Vue 2 中的使用
2.1 Vuex 的安装与配置
npm install vuex@3
然后在 Vue 根实例中引入并配置 Vuex:
javascript">// main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store' // 引入 storenew Vue({render: h => h(App),store // 确保这里注入了 Vuex store
}).$mount('#app')
2.2 Vuex 核心概念与模块
1、State
state 用于存储应用的状态。状态是集中管理的,不同组件间的共享数据都存放在 Vuex 的 state 中。
2、Getters
getters 用于从 state 中派生出一些计算值。
3、Mutations
mutations 用于同步直接修改 state。Mutation 是唯一可以直接修改 state 的方式。
4、Actions
actions 用于处理异步操作,并通过 commit 提交 mutations 来改变 state。
2.3 具体示例 🌰
目录结构
src/├── assets/├── components/├── store/│ ├── index.ts // Vuex store 的入口文件│ └── modules/│ └── cart.ts // 用于管理购物车的模块├── App.vue└── main.ts
1、cart.js 定义 Vuex 模块
javascript">// store/modules/cart.js
const cart = {namespaced: true, // 启用命名空间state: {items: []},getters: {// 获取购物车中的商品总数itemCount(state) {return state.items.reduce((count, item) => count + item.quantity, 0)},// 计算购物车中的总价totalPrice(state) {return state.items.reduce((total, item) => total + item.price * item.quantity, 0)}},mutations: {// 添加商品到购物车addItem(state, item) {const existingItem = state.items.find(i => i.id === item.id)if (existingItem) {existingItem.quantity += item.quantity} else {state.items.push(item)}},// 删除购物车中的商品removeItem(state, itemId) {state.items = state.items.filter(item => item.id !== itemId)},// 更新商品的数量updateItemQuantity(state, { itemId, quantity }) {const item = state.items.find(item => item.id === itemId)if (item) {item.quantity = quantity}}},actions: {// 异步添加商品到购物车addItemAsync({ commit }, item) {setTimeout(() => {commit('addItem', item)}, 1000)},// 异步删除商品removeItemAsync({ commit }, itemId) {setTimeout(() => {commit('removeItem', itemId)}, 1000)}}
}export default cart
2、store/index.js 注册 Vuex 模块
javascript">// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import cart from './modules/cart' // 导入 cart 模块Vue.use(Vuex)export default new Vuex.Store({modules: {cart // 注册 cart 模块}
})
3、在 App.vue 中使用 Vuex
<template><div id="app"><h1>购物车</h1><div><p>购物车商品总数:{{ itemCount }}</p><p>购物车总价:{{ totalPrice }} 元</p></div><div><button @click="addItemToCart">添加商品</button><button @click="removeItemFromCart">删除商品</button></div></div>
</template>
<script>
import { mapState, mapActions } from 'vuex'export default {computed: {// 使用命名空间,映射 cart 模块的状态...mapState('cart', ['items']),itemCount() {return this.$store.getters['cart/itemCount'] // 获取购物车商品总数},totalPrice() {return this.$store.getters['cart/totalPrice'] // 获取购物车总价}},methods: {...mapActions('cart', ['addItemAsync', 'removeItemAsync']), // action 方法映射addItemToCart() {const newItem = { id: 1, name: '商品A', price: 100, quantity: 1 }this.addItemAsync(newItem)},removeItemFromCart() {this.removeItemAsync(1)}}
}
</script>
页面展示为:
3. Vuex 在 Vue 3 中的改进
Vuex 的状态更新是响应式的,更新后的状态会自动反映到视图中。
3.1 Vue 3 新特性对 Vuex 的影响
Vue 3 引入了许多新特性,如 Composition API,这些特性对 Vuex 的使用方式产生了一定的影响。Vue 3 强调逻辑的组合性和函数式编程,因此许多开发者希望在 Vue 3 中能够采用更灵活的状态管理方案。
Vuex 4.0 版本的更新
Vue 3 发布后,Vuex 也做了相应的版本更新,即 Vuex 4.x。Vuex 4.x 是专门为 Vue 3 提供的版本,主要改进和新增了以下几个方面:
- 支持 Vue 3 的响应式系统:Vuex 4.x 能够与 Vue 3 的响应式系统更好地结合。通过 Vue 3 的 reactive、ref 等 API,Vuex 更加高效。
- 使用 Composition API 的支持:Vuex 4.x 可以和 Vue 3 的 Composition API 一起使用,为开发者提供了更灵活的状态管理方法。
3.2 Vuex 的安装与配置
在 Vue 3 中使用 Vuex,首先需要安装 Vuex 4.x:
javascript">npm install vuex@next
然后在 Vue 根实例中引入并配置 Vuex:
javascript">import { createApp } from 'vue'
import App from './App.vue'
import store from './store' // 引入 storecreateApp(App).use(store) // 使用 Vuex store.mount('#app')
3.3 具体示例 🌰
延用购物车 cart 的示例
1、cart.js 定义 Vuex 模块 --- 不变
2、store/index.js 注册 Vuex 模块
javascript">// store/index.ts
import { createStore } from 'vuex'
import cart from './modules/cart'const store = createStore({modules: {cart}
})export default store
3、在 App.vue 中使用 Vuex
Tip:store.commit 用于触发 mutation,而 mutation 是同步操作。如果需要执行异步操作,使用 store.dispatch 来触发 actions。
<template><div id="app"><h1>购物车</h1><div><p>购物车商品总数:{{ itemCount }}</p><p>购物车总价:{{ totalPrice }} 元</p></div><div><button @click="addItemToCart">添加商品</button><button @click="removeItemFromCart">删除商品</button></div></div>
</template><script>
import { defineComponent, computed } from 'vue'
import { useStore } from 'vuex'export default defineComponent({setup() {const store = useStore()const itemCount = computed(() => store.getters['cart/itemCount'])const totalPrice = computed(() => store.getters['cart/totalPrice'])const addItemToCart = () => {const newItem = { id: 1, name: '商品A', price: 100, quantity: 1 }store.dispatch('cart/addItemAsync', newItem)}const removeItemFromCart = () => {store.dispatch('cart/removeItemAsync', 1)}return {itemCount,totalPrice,addItemToCart,removeItemFromCart}}
})
</script>
页面展示:
4. Vuex 与 Vue 3 新状态管理工具 Pinia 的对比
4.1 为什么 Vue 3 引入 Pinia?
Pinia 是 Vue 3 推荐的状态管理工具,它旨在替代 Vuex,尤其是在 Vue 3 中。其设计目标是简化 API,提供更好的 TypeScript 支持,并与 Vue 3 的 Composition API 完美集成。
4.2 Vuex vs Pinia(Vue 3)对比
特性 | Vuex | Pinia |
---|---|---|
适用 Vue 版本 | Vue 2 和 Vue 3(但是 Vue 3 支持较弱) | 只支持 Vue 3 |
API 风格 | 类似于 Flux(state,mutations,actions,getters) | 现代化的 API(state,actions,getters) |
类型支持 | TypeScript 支持不完善 | 完美支持 TypeScript |
与 Vue 3 的兼容性 | 不完美,Vue 3 Composition API 集成差 | 完美兼容,支持 Vue 3 Composition API |
模块化 | 支持模块化(但需要显式声明 namespaced) | 模块化非常灵活,天然支持模块化 |
易用性 | 配置繁琐,特别是在大型项目中 | 简洁易用,API 简单直观 |
性能 | 性能不错,但对于大型应用可能较重 | 性能优化,轻量级,适合 Vue 3 环境 |
Vuex 与 Pinia 的选择建议
对于新的 Vue 3 项目,建议使用 Pinia,尤其是在需要高度类型推导和简洁 API 的场景中。对于现有的 Vue 2 项目,Vuex 仍然是推荐的选择。