大家好!我是大华。
在整个Vue生态中有两个最流行的状态管理工具:Pinia和Vuex。这篇文章会介绍这两种不同工具在项目中是如何使用的。
想象一下,你的Vue应用就像一个大家庭,各个组件就是家庭成员。当家庭成员越来越多,共享信息(比如用户登录状态、主题设置等)就变得困难了。
状态管理就像一个家庭微信群,让所有成员都能方便地获取和更新共享信息,而不需要一层层传递。
Pinia实际上是Vuex的续作,由Vue核心团队开发,可以看作是Vuex的现代化替代方案。它们的关系类似于:
Vuex有四个核心概念,记住它们就掌握了Vuex:
1.State:存储数据的地方,相当于组件的data 2.Getters:相当于计算属性,用于派生状态 3.Mutations:唯一能同步修改State的方法 4.Actions:处理异步操作,提交Mutations来修改State
|
1 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 |
// store/index.js import { createStore } from 'vuex' export default createStore({ state: { count: 0, user: null }, getters: { doubleCount: (state) => state.count * 2, getUserName: (state) => (defaultName) => state.user?.name || defaultName }, mutations: { increment(state) { state.count++ }, setUser(state, user) { state.user = user } }, actions: { async fetchUser({ commit }, userId) { const response = await fetch(`/api/users/${userId}`) const user = await response.json() commit('setUser', user) } } }) |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<template> <div> <p>计数: {{ count }}</p> <p>双倍: {{ doubleCount }}</p> <button @click="$store.commit('increment')">增加</button> <button @click="$store.dispatch('fetchUser', 1)">获取用户</button> </div> </template> <script> import { mapState, mapGetters } from 'vuex' export default { computed: { ...mapState(['count']), ...mapGetters(['doubleCount']) } } </script> |
Pinia简化了Vuex的概念:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// stores/counter.js import { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', { state: () => ({ count: 0, user: null }), getters: { doubleCount: (state) => state.count * 2, getUserName: (state) => (defaultName) => state.user?.name || defaultName }, actions: { increment() { this.count++ }, async fetchUser(userId) { const response = await fetch(`/api/users/${userId}`) this.user = await response.json() } } }) |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<template> <div> <p>计数: {{ counter.count }}</p> <p>双倍: {{ counter.doubleCount }}</p> <button @click="counter.increment()">增加</button> <button @click="counter.fetchUser(1)">获取用户</button> </div> </template> <script setup> import { useCounterStore } from '@/stores/counter' const counter = useCounterStore() </script> |
| 特性 | Vuex | Pinia |
|---|---|---|
| Vue版本 | Vue 2/3 | 主要为Vue 3设计 |
| 类型支持 | 需要额外配置 | 原生TypeScript支持 |
| 代码量 | 较多 | 更简洁 |
| 学习曲线 | 较陡峭 | 更平缓 |
| 异步处理 | 通过actions | 直接在actions中处理 |
| 模块化 | modules系统 | 多个独立store文件 |
| 开发体验 | 较繁琐 | 更简单直观 |
Vuex实现:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// store/modules/cart.js export default { state: { items: [] }, mutations: { ADD_ITEM(state, item) { state.items.push(item) } }, actions: { async addItem({ commit }, item) { // 验证逻辑... commit('ADD_ITEM', item) } } } |
Pinia实现:
|
1 2 3 4 5 6 7 8 9 10 |
// stores/cart.js export const useCartStore = defineStore('cart', { state: () => ({ items: [] }), actions: { async addItem(item) { // 验证逻辑... this.items.push(item) } } }) |
明显Pinia版本更加简洁直观!
Vuex:成熟稳定,适合需要严格规范的大型项目
Pinia:现代简洁,Vue 3项目的首选
关系:Pinia是Vuex的进化版,吸收了其优点并简化了API
建议:新项目直接用Pinia,老项目可逐步迁移
状态管理是Vue开发中的重要概念,掌握Pinia和Vuex能让你更从容地应对复杂应用开发。
本文首发于公众号:程序员刘大华,专注分享前后端开发的实战笔记。关注我,少走弯路,一起进步!
📌 扩展阅读:
《SpringBoot 中的 7 种耗时统计方式,你用过几种?》
《MySQL 为什么不推荐用雪花ID 和 UUID 做主键?》