为什么建议你用 Pinia 替换 Vuex?

Pinia被Vue.js官方推荐为状态管理工具,相较于Vuex,它提供了更强的自动补全、DevTools支持、热模块替换、SSR支持和可扩展性。Pinia的API设计直观, TypeScript支持更好,且舍弃了Mutations和模块,拥有更好的模块结构。尽管Vuex有模块化和HMR支持等优点,但Pinia的诸多优势使其成为Vue项目的新选择。

在这里插入图片描述

在 Vue.js 项目状态管理技术选型时,经常会遇到选择 Vuex 还是 Pinia 的问题。Pinia 被 Vue.js 官方网站列为 Vue.js 的推荐状态管理工具,这可能是它被受欢迎的原因之一。在本文中,将对 Pinia 和 Vuex 进行详细的对比,阐述它们的独特功能、预期用途以及优缺点,希望对您的项目技术选型有所帮助。

1.基本介绍

1.1.Pinia

Pinia 是新一代状态管理工具,它允许您在 Vue.js 组件间跨组件或页面共享状态。它也是目前官网推荐的全局状态管理工具。Vue 核心团队成员 Eduardo San Martin Morote 设计了 Pinia。通过使用新的响应性机制,Pinia 构建了一个易于使用且具有适当类型的状态管理系统,是管理应用程序响应式状态的一个优秀库。与 Vuex 相比,Pinia 的 API 学习曲线更平缓,让您的代码更易读。

使用 Pinia 创建一个 store示例:

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => {
    return { count: 0 }
  },
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++
    },
  },
})

1.2.Vuex

Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式, 它采用集中式存储管理所有组件的公共状态, 并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex 中创建一个 store 示例:

import { createStore } from 'vuex'

const counterstore = createStore({
  state() {
    return {
      todoListItems: []
    }
  },
  getters: {
    countList(state) {
      return state.todoListItems.length()
    }
  },
  actions: {
    addNewToList({commit}, item) {
      commit('createNewItem', item)
    }
  },
  mutations: {
    createNewItem(state, item) {
      state.todoListItems.push(item)
    }
  }
})

2.Pinia vs Vuex 优缺点对比

2.1.Pinia 优点

  • 🎉 强大的自动补全:Pinia 为 TypeScript 提供了强大的支持,包括针对 JavaScript 的强大自动补全功能,大大简化了开发过程。开发人员可以快速编写代码并避免常见错误,从而提高代码质量并缩短开发时间。
  • 🎉 DevTools支持:Pinia 为 Vue devtools 提供了出色的支持,允许开发人员轻松调试和监控其应用程序的状态及变更。
  • 🎉 热模块替换:通过热模块替换,开发人员可以对代码进行更改,而更改会立即反映在运行的应用程序中,从而改进开发工作流程并缩短开发时间。如果没有 Pinia,全局状态可能会在 HMR 期间被破坏和重置,但 Pinia 会保留它。
  • 🎉 支持 SSR:Pinia 支持服务器端渲染(SSR),使开发人员能够在 SSR Vue.js框架(如 Nuxt)中使用 Pinia。
  • 🎉 可扩展性:Pinia store 可通过底层 API 进行全面扩展。利用插件,您可以执行本地 localStorage 同步、ORM(对象关系映射)、定义存储时添加选项等任务,当 Pinia 的默认行为无法满足您的需求时,您还可以利用更多插件。您可以开始使用或根据自己的需要创建插件。

2.2.Vuex 优点

  • 👍🏻 模块化机制:通过利用 Vuex 模块化特性,我们可以根据业务需求将状态分为几个文件(一般考虑以页面为单位划分),您可以使用命名空间管理模块中的状态周期。随着应用程序的增长,可以引入模块按需加载策略,进一步提升页面加载性能。
  • 👍🏻 HMR 支持:Vuex 支持热重载功能,利用 webpack 的热模块替换 API,可以在开发代码时快速重新加载state、mutations、action 和getter。
  • 👍🏻 DevTools支持:可以使用 Vue devtools 中的 Vuex 选项卡方便地访问和调试mutation,以及查看状态,为我们提供了一种轻松跟踪应用程序状态的方法。

3.选择 Pinia 的理由

Pinia 和 Vuex 设计类似,都沿用 Flux 的思想,并针对 Vue 框架单独进行了一些设计上的优化。但 Pinia 在许多方面优于其他解决方案,包括 Vuex。主要优势如下:

1)直观的设计:

Pinia 的 API 设计简单直接,使创建和组织存储变得简单,类似于创建组件。这种方法减少了需要模板代码的需求,不用像 Vuex 一样去关注 commit 还是 dispatch。Pinia 为开发人员提供了一种更容易更好地理解您的 store 的方式。

2)更好的 TS 支持:

无需创建自定义的复杂封装程序来支持 TypeScript,所有内容都是类型化的,API 的设计方式也尽可能利用了 TS 类型推断。

3)舍弃了 Mutations 和 module:

Pinia 并非完全抛弃了 mutation,而是将对 state 中单个数据进行修改的操作封装为一个 mutation,但不对外开放接口。可以在 devtools 中观察到 mutation。

Pinia 通过在创建 store 时指定 name 来区分不同的 store,不再需要 module。

4)更好的模块结构:

模块结构不再嵌套。您仍然可以通过导入和使用一个存储空间来隐式嵌套另一个存储空间,但 Pinia 通过设计提供了一种扁平结构,同时仍然支持存储空间之间的交叉组合方式。

5)天生的轻量:

Pinia 只有 1KB,非常容易集成到您的项目中。这可能会提高应用程序的性能。

总结

Pinia 和 Vuex 两个状态管理库各有优势,但 Pinia 与 Vuex 相比优势更加明显。另外,Pinia 已被指定为官方推荐的状态管理库,因此是构建 Vue.js 应用程序的不二之选。

如果您已经有在 Vuex 上运行的项目,不建议进行迁移,毕竟迁移需要成本。如果您正在考虑新的项目技术选型,推荐你选择 Pinia!

关注FED实验室公众号,获取更多前端热点资讯。
在这里插入图片描述

在现代 Vue 3 项目中,**推荐使用 Pinia不是 Vuex**。尤其是你正在开发一个基于 `Vue 3 + Vite + TypeScript` 的 Chrome 扩展插件(如侧边栏应用),Pinia 是官方推荐的状态管理方案,也是未来 Vue 生态的标准。 --- ## ✅ 结论先行 > **用 Pinia,不要用 Vuex**。 Vuex 已经进入维护模式,不再接受新功能;而 **PiniaVue 团队官方推荐的下一代状态管理工具**,更简洁、更类型安全、更易用。 --- ## 🆚 对比:Pinia vs VuexVue 3 环境下) | 特性 | Pinia | Vuex | |------|-------|------| | ✅ 官方推荐 | ✔️ 是(Vue 3+) | ❌ 否(已归档) | | 🔤 TypeScript 支持 | 原生支持,无需额外声明 | 需要手动定义类型,较复杂 | | 📦 模块化结构 | 天然模块化(每个 store 独立) | 需通过 modules 实现 | | 🧩 API 设计 | 组合式 API 风格,`setup()` 友好 | 选项式为主,与 Composition API 不够融合 | | 🖥️ DevTools 支持 | ✔️ 完全支持 | ✔️ 支持但更新缓慢 | | 📁 包体积 | 更小(~1KB gzipped) | 相对更大 | | 🔄 HMR 热重载 | ✔️ 支持模块热替换 | ❌ 不支持 | | 🛠️ 调试体验 | 更清晰的 action 追踪 | 传统 mutation/action 分离略繁琐 | > 🔴 Vuex 5 正在开发中,未来可能会借鉴 Pinia 的设计。 --- ## 💡 为什么在你的“侧边栏扩展”项目中更适合用 Pinia? ### 场景回顾: - 多页面路由history / settings / analysis) - 需要在 Content Script、Side Panel、Background 之间通信 - 使用 `chrome.storage` 持久化数据 - 需要共享状态:比如用户设置、选择历史、是否启用 AI 分析等 ### ✅ Pinia 的优势体现: #### 1. **TypeScript 开箱即用** ```ts // stores/useSettingsStore.ts import { defineStore } from 'pinia' export const useSettingsStore = defineStore('settings', { state: () => ({ autoHighlight: false, darkMode: true, apiUrl: 'https://api.example.com' }), actions: { setHighlight(value: boolean) { this.autoHighlight = value // 同步到 chrome.storage chrome.storage.sync.set({ autoHighlight: value }) } }, getters: { modeLabel: (state) => (state.darkMode ? '深色主题' : '浅色主题') } }) ``` ✅ 类型自动推导,无需写接口或映射。 --- #### 2. **组合式风格,易于测试和复用** ```ts // composables/useTextHistory.ts import { useSettingsStore } from '@/stores/useSettingsStore' export function useTextHistory() { const settings = useSettingsStore() const history = ref<string[]>([]) async function loadHistory() { const res = await chrome.storage.local.get(['history']) history.value = res.history || [] } function addRecord(text: string) { if (settings.autoHighlight) { history.value.unshift(text) if (history.value.length > 50) history.value.pop() chrome.storage.local.set({ history: history.value }) } } return { history, loadHistory, addRecord } } ``` ✅ 可以自由组合 store 和业务逻辑。 --- #### 3. **跨上下文状态同步(配合 chrome.storage)** 虽然 Pinia 本身是内存级状态管理,但我们可以通过监听 `chrome.storage.onChanged` 来实现多上下文同步: ```ts // stores/useSettingsStore.ts watch( () => settings.autoHighlight, (value) => { chrome.storage.sync.set({ autoHighlight: value }) } ) chrome.storage.onChanged.addListener((changes) => { if (changes.autoHighlight) { settings.autoHighlight = changes.autoHighlight.newValue } }) ``` 这样即使在 Content Script 修改了设置,Side Panel 也能实时响应。 --- #### 4. **DevTools 调试清晰** 打开 Chrome DevTools → Pinia 面板: - 查看所有 store 的 state - 调用 action - 时间旅行调试(需配置) --- ## 🧱 如何集成 Pinia 到你的项目 ### 1. 安装依赖 ```bash npm install pinia ``` ### 2. 在 `main.ts` 中注册 ```ts // src/main.ts import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import router from './router' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' const pinia = createPinia() createApp(App) .use(pinia) .use(router) .use(ElementPlus) .mount('#app') ``` --- ### 3. 创建第一个 Store(示例:文本历史) ```ts // stores/useHistoryStore.ts import { defineStore } from 'pinia' export const useHistoryStore = defineStore('history', { state: () => ({ records: [] as Array<{ text: string; url: string; timestamp: number }> }), getters: { count: (state) => state.records.length, recentRecords: (state) => state.records.slice(0, 10) }, actions: { async fetchFromStorage() { const res = await chrome.storage.local.get(['historyRecords']) this.records = res.historyRecords || [] }, addRecord(text: string, url: string) { this.records.unshift({ text, url, timestamp: Date.now() }) if (this.records.length > 100) this.records.length = 100 this.saveToStorage() }, saveToStorage() { chrome.storage.local.set({ historyRecords: this.records }) } } }) ``` --- ### 4. 在组件中使用 ```vue <script setup lang="ts"> import { useHistoryStore } from '@/stores/useHistoryStore' const historyStore = useHistoryStore() // 自动从 storage 加载 historyStore.fetchFromStorage() // 接收 content script 消息 chrome.runtime.onMessage.addListener((msg) => { if (msg.type === 'TEXT_SELECTED') { historyStore.addRecord(msg.text, msg.url) } }) </script> <template> <div v-for="item in historyStore.recentRecords" :key="item.timestamp"> {{ item.text }} </div> </template> ``` --- ## ⚠️ 注意事项(Chrome 扩展特有) | 问题 | 解决方案 | |------|----------| | ❌ 内存状态不能跨页持久 | 必须结合 `chrome.storage` 持久化 | | ✅ 使用 `chrome.storage.onChanged` 同步多个上下文 | 在各 store 中监听变更 | | 🔄 避免频繁写 storage | 可加防抖或批量提交 | | 🔐 敏感数据加密 | 如 token 应使用 `chrome.storage.session` | --- ## ✅ 总结:你应该选择 Pinia 的理由 | 如果你是…… | 推荐 | |------------|------| | 新项目开发者 | ✅ 强烈推荐 Pinia | | 团队协作项目 | ✅ 更清晰的代码结构 | | 需要 TypeScript 支持 | ✅ Pinia 类型推导更强 | | 想快速上手 | ✅ API 更简单直观 | | 维护老项目 | ⚠️ 可继续用 Vuex,但建议逐步迁移 | > 🔚 **一句话总结:** > > “PiniaVue 3 时代的 Vuex 替代品 —— 更轻、更快、更智能。” ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值