别再纠结Pinia和Vuex了!一篇文章彻底搞懂区别与选择

大家好!我是大华。

在整个Vue生态中有两个最流行的状态管理工具:Pinia和Vuex。这篇文章会介绍这两种不同工具在项目中是如何使用的。

状态管理是什么?为什么需要它?

想象一下,你的Vue应用就像一个大家庭,各个组件就是家庭成员。当家庭成员越来越多,共享信息(比如用户登录状态、主题设置等)就变得困难了。

状态管理就像一个家庭微信群,让所有成员都能方便地获取和更新共享信息,而不需要一层层传递。

Pinia和Vuex的关系

Pinia实际上是Vuex的续作,由Vue核心团队开发,可以看作是Vuex的现代化替代方案。它们的关系类似于:

  • Vuex是Vue2时代的官方状态管理方案
  • Pinia是Vue3时代官方推荐的状态管理方案
  • Pinia吸收了Vuex的优点,同时简化了API
  • 两者可以共存,但新项目建议使用Pinia

Vuex详解

核心概念

Vuex有四个核心概念,记住它们就掌握了Vuex:

1.State :存储数据的地方,相当于组件的data 2.Getters :相当于计算属性,用于派生状态 3.Mutations :唯一能同步修改State的方法 4.Actions:处理异步操作,提交Mutations来修改State

完整示例

javascript 复制代码
// 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)
    }
  }
})

组件中使用

html 复制代码
<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详解

核心特点

Pinia简化了Vuex的概念:

  1. 没有Mutations,只有State、Getters、Actions
  2. 完全支持TypeScript,类型推断非常友好
  3. 更简洁的API,更少的模板代码
  4. 支持Composition API和Options API两种风格

完整示例

javascript 复制代码
// 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()
    }
  }
})

组件中使用

vue 复制代码
<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. 维护现有的Vuex项目
  2. 需要严格的变更追踪(mutations提供明确记录)
  3. 大型团队需要严格的代码规范
  4. Vue2项目

选择Pinia的情况:

  1. 新开始的Vue 3项目
  2. 需要良好的TypeScript支持
  3. 追求简洁的API和开发效率
  4. 中小型项目

购物车场景对比

Vuex实现:

javascript 复制代码
// 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实现:

javascript 复制代码
// 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 做主键?》

《Vue3 如何优雅地实现一个全局的 loading 组件》

《Vue3+CSS实现一个非常丝滑的 input 标签上浮动画》

相关推荐
小蹦跶儿5 分钟前
解决Webpack 打包报错:TypeError: Cannot assign to read only property 'exports' ?
javascript·vue.js·webpack
fruge10 分钟前
前端注释规范:如何写“后人能看懂”的注释(附示例)
前端
老华带你飞11 分钟前
医疗保健|医疗养老|基于Java+vue的医疗保健系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·医疗保健
小飞大王66619 分钟前
JavaScript基础知识总结(四):常见内置构造函数,正则表达式,作用域与闭包
前端·javascript·正则表达式
清凉夏日38 分钟前
Flutter 国际化完整指南
前端·flutter
Jony_1 小时前
动态代理机制
前端
掘金一周1 小时前
重新思考 weapp-tailwindcss 的未来 | 掘金一周 11.13
前端·人工智能·后端
Pu_Nine_91 小时前
Vue 3 项目 ESLint 配置详解:初始模板的正确配置
前端·javascript·vue.js
Jolyne_1 小时前
【浏览器插件】一键下载页面图片和文本
前端
Jony_1 小时前
Android 类加载机制
前端·客户端