当前位置: 首页 > news >正文

【Vue学习笔记】状态管理:Pinia 与 Vuex 的使用方法与对比【附有完整案例】

最近在接手vue项目的需求,因为之前一直在做react的需求,日常的vue练习也少了很多,导致现在接手vue项目,很多关于vue的知识点基本上忘得干干净净了。但是好在有基础,重新学也会很快掌握。分享这个过程中的一些复习内容。

本篇分享【状态管理】相关的内容。


一、状态管理概述

状态管理用于解决 Vue 应用中组件间的数据共享问题,尤其适合以下场景:

  • 多个组件需要共享同一数据
  • 不同组件需要修改同一份数据
  • 跨层级组件间的通信

Vuex 作为 Vue 官方推荐的状态管理库已有多年历史,而 Pinia 则是 Vuex 团队在 Vue 3 时代推出的新方案,目前已成为 Vue 3 项目的官方推荐。

二、Vuex 4.x 的使用方法

Vuex 4 专为 Vue 3 设计,保留了 Vuex 的核心概念,但做了适配 Composition API 的改进。

1. 安装与配置

npm install vuex@4

创建 store/index.js:

import { createStore } from 'vuex'export default createStore({state() {return {count: 0,message: 'Hello from Vuex'}},mutations: {increment(state) {state.count++},updateMessage(state, newMessage) {state.message = newMessage}},actions: {async updateMessageAsync(context, newMessage) {// 模拟API请求await new Promise(resolve => setTimeout(resolve, 500))context.commit('updateMessage', newMessage)}},getters: {doubleCount(state) {return state.count * 2}}
})

在 main.js 中引入:

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'createApp(App).use(store).mount('#app')

2. 核心概念

  • State:存储应用状态的数据源
  • Mutations:唯一可以修改 state 的同步函数
  • Actions:处理异步操作,通过 commit 调用 mutations
  • Getters:从 state 派生出的计算属性

3. 组件中使用

src/component/VuexPage1.vue

<template><div class="vuex-page1"><h2>Vuex Page 1</h2><p>Count from store: {{ $store.state.count }}</p><p>Double Count: {{ $store.getters.doubleCount }}</p><p>Message: {{ $store.state.message }}</p><button @click="$store.commit('decrement')">Decrement</button><button @click="$store.dispatch('increment')">Increment (via action)</button><button @click="updateMessage">Change Message</button></div>
</template><script setup>
import { useStore } from 'vuex'// 获取store实例
const store = useStore()// 组件方法
const updateMessage = () => {store.commit('updateMessage', 'Updated from Vuex Page 1')
}
</script><style scoped>
.vuex-page1 {padding: 20px;border: 1px solid #42b983;margin: 10px;background-color: #f0fdf4;
}button {margin: 0 5px;padding: 5px 10px;cursor: pointer;
}
</style>

src/component/VuexPage2.vue

<template><div class="vuex-page2"><h2>Vuex Page 2</h2><p>Count from store: {{ $store.state.count }}</p><p>Double Count: {{ $store.getters.doubleCount }}</p><p>Message: {{ $store.state.message }}</p><button @click="$store.commit('increment')">Increment</button><button @click="$store.commit('reset')">Reset Count</button><button @click="updateMessageAsync">Change Message (Async)</button></div>
</template><script setup>
import { useStore } from 'vuex'// 获取store实例
const store = useStore()// 组件方法
const updateMessageAsync = () => {store.dispatch('updateMessageAsync', 'Updated from Vuex Page 2 (Async)')
}
</script><style scoped>
.vuex-page2 {padding: 20px;border: 1px solid #3498db;margin: 10px;background-color: #f0f7ff;
}button {margin: 0 5px;padding: 5px 10px;cursor: pointer;
}
</style>

App.vue

<template><div id="app"><h1>Vuex Store Test</h1><VuexPage1 /><VuexPage2 /></div>
</template><script setup>
import VuexPage1 from './components/VuexPage1.vue'
import VuexPage2 from './components/VuexPage2.vue'
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

 4.效果展示

Decrement:减一操作

Increment:加一操作

Change Message:改成状态库中message的值

Increment (via action): “通过 action 方式(实现的)递增”

两种修改状态的方式:

  • 直接通过 mutation 修改($store.commit('increment')
  • 通过 action 间接修改($store.dispatch('increment'),然后在 action 内部再调用 mutation)

Change Message (Async):异步

三、Pinia 的使用方法

Pinia 是 Vuex 的继任者,简化了状态管理的写法,天然支持 TypeScript,更符合 Vue 3 的 Composition API 风格。

1. 安装与配置

npm install pinia

创建 store/index.js:

import { createPinia } from 'pinia'
export default createPinia()

创建 store/counterStore.js:

import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => ({count: 0,message: 'Hello from Pinia'}),actions: {increment() {this.count++},async updateMessageAsync(newMessage) {await new Promise(resolve => setTimeout(resolve, 500))this.message = newMessage}},getters: {doubleCount() {return this.count * 2}}
})

在 main.js 中引入:

import { createApp } from 'vue'
import App from './App.vue'
import store from './store'createApp(App).use(store).mount('#app')

2. 核心概念

  • Store:每个 store 都是一个独立的模块
  • State:存储状态的数据源
  • Actions:可以包含同步和异步操作,直接修改 state
  • Getters:计算属性,基于 state 派生

3. 组件中使用

src/component/Page1.vue

<template><div class="page1"><h2>Page 1</h2><p>Count from store: {{ counterStore.count }}</p><p>Message: {{ counterStore.message }}</p><button @click="counterStore.increment">Increment</button><button @click="counterStore.decrement">Decrement</button><button @click="counterStore.changeMultiplier(5)">changeMultiplier</button><button @click="beMultiplier">beMultiplier</button><button @click="changeMessage">Change Message</button></div>
</template><script setup>
import { useCounterStore } from '../store/counterStore'// 获取store实例
const counterStore = useCounterStore()// 组件方法
const changeMessage = () => {counterStore.updateMessage('Updated from Page 1')
}
const beMultiplier=()=>{counterStore.beMultipliedBy(4)
}
</script><style scoped>
.page1 {padding: 20px;border: 1px solid #ccc;margin: 10px;
}button {margin: 0 5px;padding: 5px 10px;
}
</style>

src/component/Page2.vue

<template><div class="page2"><h2>Page 2</h2><p>Count from store: {{ counterStore.count }}</p><p>Message: {{ counterStore.message }}</p><button @click="counterStore.increment">Increment</button><button @click="counterStore.reset">Reset Count</button><button @click="changeMessage">Change Message</button></div>
</template><script setup>
import { useCounterStore } from '../store/counterStore'// 获取store实例
const counterStore = useCounterStore()// 组件方法
const changeMessage = () => {counterStore.updateMessage('Updated from Page 2')
}
</script><style scoped>
.page2 {padding: 20px;border: 1px solid #666;margin: 10px;background-color: #f5f5f5;
}button {margin: 0 5px;padding: 5px 10px;
}
</style>

App.vue


<template><div id="app"><h1>Pinia Store Test</h1><Page1 /><Page2 /></div>
</template><script setup>
import Page1 from './components/Page1.vue'
import Page2 from './components/Page2.vue'
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;
}
</style>

4. 效果展示

 

四、Pinia 与 Vuex 的核心区别

特性Vuex 4Pinia
模块化需要通过 modules 创建模块每个 store 都是独立模块,天然支持模块化
状态修改必须通过 mutations直接在 actions 中修改,或直接修改 state
异步操作需要在 actions 中处理可以在 actions 中直接处理
TypeScript 支持有限,需要额外类型定义原生支持,类型推断更友好
代码简洁性较繁琐,需要 commit/dispatch 区分更简洁,直接调用方法
开发者工具支持支持支持,且有更好的时间线追踪
插件系统丰富兼容 Vuex 的插件,且有新的插件系统

五、如何选择

  1. 新项目:优先选择 Pinia,它是 Vue 官方推荐的最新方案,API 更简洁,TypeScript 支持更好。

  2. 已有 Vuex 项目

    • 若项目稳定运行,无需急于迁移
    • 若进行重大重构,可考虑迁移到 Pinia
    • Vuex 4 仍会维护,但不会有新功能
  3. 团队因素:如果团队已熟悉 Vuex,且项目复杂度不高,继续使用 Vuex 也是合理选择。

六、总结

Pinia 和 Vuex 都是优秀的 Vue 状态管理方案,它们解决的核心问题相同,但实现方式有所不同。

Vuex 作为成熟的状态管理库,有着完善的生态和社区支持,适合需要严格规范状态修改流程的大型项目。而 Pinia 则代表了未来的发展方向,它简化了状态管理的写法,提供了更好的开发体验和 TypeScript 支持。

http://www.dtcms.com/a/296953.html

相关文章:

  • 网络安全入门第一课:信息收集实战手册(2)
  • C语言-指针[变量指针与指针变量]
  • Java 集合框架之----ArrayList
  • Effective Modern C++ 条款16:保证const成员函数的线程安全性
  • 网址收集总结
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-17,(知识点:PCB布线,传输线阻抗影响因素)
  • 第一二章笔记
  • [ComfyUI] --ComfyUI 是什么?比 Stable Diffusion WebUI 强在哪?
  • 【STM32项目】智能台灯
  • 无人机保养指南
  • 深入解析Hadoop NameNode的Full GC问题、堆外内存泄漏及元数据分治策略
  • 软件测试的分类
  • C++实现精确延时的方法
  • 季逸超:Manus的上下文工程启示
  • Photoshop下载安装入门教程:从下载安装到第一次完美使用
  • 应急响应】Linux 自用应急响应工具发版 v6.0(LinuxGun)
  • 20 BTLO 蓝队靶场 Sticky Situation 解题记录
  • Voice AI Agent 知识库:打造你自己的语音智能体!
  • Vitest 用法详解及 Coverage Web 工具介绍
  • C# 密封类_密封方法 (seadled 关键字)
  • 【postgresql按照逗号分割字段,并统计数量和求和】
  • 【Spring AI 1.0.0】Spring AI 1.0.0框架快速入门(4)——Chat Memory(聊天记录)
  • SpringCloud【Sentinel】
  • 7.3.2 内核内存管理运行机制
  • 到底可不可以用jion?jion如何优化?
  • MapStruct类型转换接口未自动注入到spring容器中
  • Web前端:JavaScript find()函数内判断
  • Redis 单线程模型与多线程机制
  • kettle 8.2 ETL项目【二、加载数据】
  • 「Linux命令基础」用户和用户组实训