Vuex 和 Pinia 各自的優點

核心總結(一句話概括)

  • Vuex:Vue 官方曾經的狀態管理標準解決方案,成熟穩定,概念清晰,但語法稍顯冗長。
  • Pinia:Vue 官方推薦的新一代狀態管理庫,API 設計極其簡潔,完美支持 TypeScript,且兼容 Vue 2 和 3。

Vuex 的優點

Vuex 是 Vue 生態中經過長時間考驗的狀態管理庫,其優點主要體現在以下幾個方面:

  1. 成熟穩定與廣泛認可

    • Vuex 是 Vue 生態的“老大哥”,擁有悠久的歷史和龐大的用戶群體。這意味著你遇到的所有問題,幾乎都能在社區找到答案和解決方案。
    • 經過無數大型項目的檢驗,其穩定性和可靠性毋庸置疑。
  2. 清晰的架構與流程

    • Vuex 強制使用單向數據流(State -> View -> Actions -> Mutations -> State),這使得狀態變化變得可預測和易于追蹤。
    • 明確的角色分工(State, Getters, Mutations, Actions)讓代碼結構非常清晰,特別適合團隊協作,能有效規范開發者的代碼書寫方式。
  3. 強大的開發工具集成

    • Vue Devtools 對 Vuex 提供了完美的支持。你可以方便地進行時間旅行調試(Time Travel Debugging),查看每一次狀態變更的詳細記錄、觸發它的 mutation 和 action,甚至可以回退到某個歷史狀態,這對于調試復雜應用非常有用。
  4. 內置的模塊化方案

    • Vuex 提供了完整的模塊(Modules)系統,允許你將復雜的 store 分割成多個模塊,每個模塊擁有自己的 state、getters、mutations、actions,甚至可以嵌套子模塊。這對于組織大型項目的代碼非常有效。

Pinia 的優點

Pinia 由 Vue.js 核心團隊開發和維護,被譽為“下一代的 Vuex”,它吸收了許多優秀 ideas,其優點非常突出:

  1. 極其簡潔的 API 設計

    • Pinia 的 API 設計非常直觀,大大減少了模板代碼。它廢除了 Vuex 中 Mutations 的概念,只需要 state, getters, actions
    • Actions 統一處理同步和異步操作,不再需要區分是 commit 一個 mutation 還是 dispatch 一個 action,心智負擔顯著降低。
  2. 完美的 TypeScript 支持

    • Pinia 的 API 從一開始就是為 TS 設計的,提供了出色的類型推斷。你幾乎不需要編寫額外的類型定義,就能獲得完整的自動補全和類型安全檢查,開發體驗極佳。
  3. 輕量級與高性能

    • Pinia 的體積非常小(約 1KB),對 bundle 大小的影響微乎其微。
    • 其設計上沒有任何冗余,性能優秀。
  4. 模塊化是天然設計

    • Pinia 沒有嵌套模塊的概念,而是鼓勵你創建多個 store。每個 store 都是獨立的,你可以按需導入使用。這種“扁平化”的設計使得代碼結構更簡單,同時仍然可以通過在 store 中導入另一個 store 來實現交叉組合(Cross Store),非常靈活。
  5. Composition API 風格

    • Pinia 的 API 設計與 Vue 3 的 Composition API 風格高度一致,使用 refcomputed 等函數來定義 state 和 getters,對于熟悉 Composition API 的開發者來說上手幾乎沒有成本。
  6. 無需復雜的模塊注冊

    • 在 Vuex 中,你需要先將模塊注冊到根 store。而在 Pinia 中,每個 store 都是獨立定義和使用的,無需在根 store 中注冊,簡化了流程。
  7. 官方推薦與未來趨勢

    • Pinia 已經成為 Vue 官方的正式項目,并被推薦為默認的狀態管理解決方案。對于新項目,尤其是 Vue 3 項目,選擇 Pinia 意味著你選擇了未來的主流和方向。

對比表格

特性VuexPinia
適用版本Vue 2 / Vue 3Vue 2 / Vue 3
API 設計稍顯冗長,概念多(Mutations/Actions)極其簡潔,只有 state/getters/actions
TS 支持需要額外配置,支持一般完美支持,原生友好
調試工具完美支持(時間旅行)支持,但時間旅行功能尚不完善
學習曲線中等,需要理解特定概念低,更接近 Vue 組件開發思維
模塊化通過 modules 實現嵌套模塊通過多個 store 實現扁平化模塊
包大小較大非常小 (~1KB)
官方地位舊版標準新一代官方推薦

如何選擇?

  • 為新項目選擇 Pinia:毫無疑問,對于新的 Vue 2 或 Vue 3 項目,都應該優先選擇 Pinia。它更簡單、更現代、對 TypeScript 更友好,而且是官方推薦的未來。
  • 維護現有 Vuex 項目:如果你的老項目使用的是 Vuex,并且運行良好,沒有必要立刻重構成 Pinia。Vuex 4 仍然是一個穩定且功能完整的庫,會繼續得到維護。重構應該在有足夠資源和明顯收益時才進行。
  • 需要強大的時間旅行調試:如果你極度依賴 Vue Devtools 中的時間旅行調試功能來排查復雜問題,目前 Vuex 在這方面可能仍略有優勢。不過 Pinia 的調試功能也在不斷完善中。

總而言之,Pinia 在絕大多數場景下都是比 Vuex 更優的選擇,它代表了 Vue 狀態管理的未來方向。


好的,我們結合代碼來深入對比 Vuex 和 Pinia 的用法和優點。我們將以實現一個簡單的計數器(Counter)和一個異步獲取用戶信息(User)的功能為例。


1. Vuex 實現

項目結構(通常如此組織)
src/store/index.js          // 主入口,創建 root storemodules/counter.js     // 計數器模塊user.js        // 用戶模塊
代碼實現

1. 計數器模塊 (store/modules/counter.js)

// 計數器模塊
const state = {count: 0
};const getters = {doubleCount: (state) => state.count * 2,isEven: (state) => state.count % 2 === 0
};// Mutations 必須是同步函數
const mutations = {INCREMENT(state, payload) {state.count += payload;},DECREMENT(state, payload) {state.count -= payload;}
};// Actions 可以包含異步操作
const actions = {incrementAsync({ commit }, payload) {setTimeout(() => {commit('INCREMENT', payload.amount);}, 1000);}
};export default {// 開啟命名空間,避免模塊間命名沖突namespaced: true,state,getters,mutations,actions
};

2. 用戶模塊 (store/modules/user.js)

const state = {user: null,isLoading: false
};const getters = {userName: (state) => state.user?.name || 'Guest'
};const mutations = {SET_LOADING(state, isLoading) {state.isLoading = isLoading;},SET_USER(state, user) {state.user = user;}
};const actions = {async fetchUser({ commit }, userId) {commit('SET_LOADING', true);try {// 模擬異步 API 調用const response = await fetch(`https://api.example.com/users/${userId}`);const user = await response.json();commit('SET_USER', user);} catch (error) {console.error('Failed to fetch user:', error);} finally {commit('SET_LOADING', false);}}
};export default {namespaced: true,state,getters,mutations,actions
};

3. 創建 Store (store/index.js)

import { createStore } from 'vuex';
import counter from './modules/counter';
import user from './modules/user';export default createStore({modules: {counter,user}
});

4. 在 Vue 組件中使用 (Component.vue)

<template><div><h2>Counter: {{ count }}</h2><p>Double: {{ doubleCount }}, Is Even: {{ isEven }}</p><button @click="increment(1)">+1</button><button @click="incrementAsync(5)">+5 Async</button><h2>User: {{ userName }}</h2><button @click="fetchUser(123)" :disabled="isLoading">{{ isLoading ? 'Loading...' : 'Fetch User' }}</button></div>
</template><script>
import { mapState, mapGetters, mapActions } from 'vuex';export default {computed: {// 映射 counter 模塊的 state 和 getters...mapState('counter', ['count']),...mapGetters('counter', ['doubleCount', 'isEven']),// 映射 user 模塊的 state 和 getters...mapState('user', ['isLoading']),...mapGetters('user', ['userName'])},methods: {// 映射 counter 模塊的 actions...mapActions('counter', ['incrementAsync']),// 映射 user 模塊的 actions...mapActions('user', ['fetchUser']),// 直接提交 mutation (通常不推薦在組件中直接提交,應用 Action)increment(amount) {this.$store.commit('counter/INCREMENT', amount);}}
};
</script>
Vuex 代碼特點分析:
  1. 概念清晰但繁瑣:嚴格區分了 Mutations(同步)和 Actions(異步)。
  2. 模板代碼多:需要定義 state, getters, mutations, actions 四個部分,即使邏輯很簡單。
  3. 模塊化需要注冊:需要在主入口文件中注冊模塊。
  4. 命名空間:必須使用 namespaced: true 和類似 'counter/INCREMENT' 的路徑來訪問,字符串容易寫錯。
  5. TypeScript 支持較弱:需要大量手動類型定義才能獲得良好的類型推斷。

2. Pinia 實現

項目結構(更靈活,推薦按功能組織)
src/stores/counter.store.js     // 計數器 Storeuser.store.js        // 用戶 Store
代碼實現

1. 計數器 Store (stores/counter.store.js)

import { defineStore } from 'pinia';// 使用 'counter' 作為 store 的唯一 ID
export const useCounterStore = defineStore('counter', {// State 是一個函數,返回初始狀態state: () => ({count: 0}),// Getters 等同于 store 的 computed 屬性getters: {doubleCount: (state) => state.count * 2,isEven: (state) => state.count % 2 === 0},// Actions 可以是同步或異步的actions: {increment(amount) {// 在 Action 中直接修改 statethis.count += amount;},decrement(amount) {this.count -= amount;},async incrementAsync(amount) {// 異步操作同樣簡單await new Promise(resolve => setTimeout(resolve, 1000));this.increment(amount); // 可以調用其他 action}}
});

2. 用戶 Store (stores/user.store.js)

import { defineStore } from 'pinia';export const useUserStore = defineStore('user', {state: () => ({user: null,isLoading: false}),getters: {userName: (state) => state.user?.name || 'Guest'},actions: {async fetchUser(userId) {this.isLoading = true;try {const response = await fetch(`https://api.example.com/users/${userId}`);this.user = await response.json();} catch (error) {console.error('Failed to fetch user:', error);} finally {this.isLoading = false;}}}
});

3. 創建并掛載 Pinia (main.js)

import { createApp } from 'vue';
import { createPinia } from 'pinia'; // 導入 createPinia
import App from './App.vue';// 1. 創建 Pinia 實例
const pinia = createPinia();// 2. 將 Pinia 實例掛載到 Vue 應用
createApp(App).use(pinia).mount('#app');
// 注意:這里沒有像 Vuex 那樣的“主 store”需要創建和注冊模塊

4. 在 Vue 組件中使用 (Component.vue)

<template><div><h2>Counter: {{ counterStore.count }}</h2><p>Double: {{ counterStore.doubleCount }}, Is Even: {{ counterStore.isEven }}</p><button @click="counterStore.increment(1)">+1</button><button @click="counterStore.incrementAsync(5)">+5 Async</button><h2>User: {{ userStore.userName }}</h2><button @click="userStore.fetchUser(123)" :disabled="userStore.isLoading">{{ userStore.isLoading ? 'Loading...' : 'Fetch User' }}</button></div>
</template><script setup>
// 1. 導入需要的 store
import { useCounterStore } from '@/stores/counter.store';
import { useUserStore } from '@/stores/user.store';// 2. 在 setup() 中調用它們
// Pinia 會自動處理依賴和單例,你可以在任何地方調用,它都會返回同一個實例。
const counterStore = useCounterStore();
const userStore = useUserStore();// 如果你需要解構 store 以保持響應性,可以使用 storeToRefs
// import { storeToRefs } from 'pinia';
// const { count, doubleCount } = storeToRefs(counterStore);
// const { isLoading, userName } = storeToRefs(userStore);
</script>
Pinia 代碼特點分析:
  1. API 極其簡潔:只有一個 defineStore 函數,包含 state, getters, actions 三個部分。廢除了 mutations
  2. 直接修改狀態:在 actions 中,可以直接通過 this.count 修改狀態,無需 commit。同步和異步操作寫法統一。
  3. TypeScript 完美支持:所有類型都是自動推斷的。useCounterStore 具有完整的類型信息。
  4. 模塊化是天然的:每個 store 都是一個獨立的文件,通過 useXxxStore 函數按需引入和使用,無需在中心點注冊。
  5. 與 Composition API 完美融合:在 <script setup> 中使用,感覺就像在使用一個組合式函數,非常自然。
  6. 無命名空間煩惱:每個 store 本身就是一個“命名空間”,直接通過 store.prop 訪問,沒有字符串路徑。

總結對比

操作VuexPinia優勢方
定義 Statestate: { count: 0 }state: () => ({ count: 0 })Pinia (函數式,更好的 TS 支持)
定義 Gettergetters: { double: (s) => s.count * 2 }getters: { double: (s) => s.count * 2 }平手
同步更新commit('INCREMENT', payload)this.count += payloadPinia (更直觀,代碼少)
異步操作dispatch('incrementAsync', payload)this.incrementAsync(payload)Pinia (統一用 action,無歧義)
模塊化創建模塊,在主 store 中注冊創建獨立 store,直接引入使用Pinia (更靈活,無注冊負擔)
組件中使用mapState, mapActions 輔助函數直接調用 useStore() 函數Pinia (與 Composition API 結合更緊密)
TS 體驗需要大量手動定義類型完全自動的類型推斷Pinia (壓倒性優勢)

結論:
從代碼層面可以清晰地看到,Pinia 的語法更加現代、簡潔和直觀。它消除了 Vuex 中一些令人困惑的概念(如 Mutations),提供了卓越的 TypeScript 開發體驗,并且與 Vue 3 的 Composition API 哲學完美契合。對于新項目,Pinia 是毫無疑問的更優選擇。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96871.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96871.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96871.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

幾種方式實現文件自動上傳到服務器共享文件夾

文章目錄一、方案核心邏輯二、詳細實現步驟&#xff08;以Windows系統為例&#xff09;1. 確認服務器共享文件夾的“訪問權限”&#xff08;前提&#xff09;2. 選擇“傳輸觸發方式”&#xff08;按需求選實時/周期&#xff09;&#xff08;1&#xff09;周期傳輸&#xff08;如…

Milvus介紹及多模態檢索實踐

1、核心組件 1.1 Collection (集合) 可以用一個圖書館的比喻來理解 Collection&#xff1a; Collection (集合): 相當于一個圖書館&#xff0c;是所有數據的頂層容器。一個 Collection 可以包含多個 Partition&#xff0c;每個 Partition 可以包含多個 Entity。 Partition (分區…

第二十三天-LCD液晶顯示實驗

一、LCD結構體定義LCD為LCD_TypeDef類型的指針&#xff0c;指向0x6C000000的地址空間&#xff08;bank1分區4的地址范圍&#xff09;。為什么需要并上0x000007FE呢&#xff1f;因為雖然驅動SRAM的時序和16位8080接口時序&#xff08;驅動LCD時序&#xff09;很像&#xff0c;但…

SQL性能調優

MySQL出現性能差的原因有哪些? 可能是 SOL查詢使用了全表掃描&#xff0c;也可能是查詢語句過于復雜&#xff0c;如多表 IOIN 或嵌套子查詢。 也有可能是單表數據量過大。 通常情況下&#xff0c;添加索引就能解決大部分性能問題。對于一些熱點數據&#xff0c;還可以通過增加…

dapo:開源大規模llm強化學習系統的突破與實現

本文由「大千AI助手」原創發布&#xff0c;專注用真話講AI&#xff0c;回歸技術本質。拒絕神話或妖魔化。搜索「大千AI助手」關注我&#xff0c;一起撕掉過度包裝&#xff0c;學習真實的AI技術&#xff01; ? 1. dapo概述&#xff1a;開源llm強化學習系統的重要突破 dapo&…

【車載開發系列】ParaSoft集成測試環境配置(五)

【車載開發系列】ParaSoft集成測試環境配置(五) 【車載開發系列】ParaSoft集成測試環境配置(五) 【車載開發系列】ParaSoft集成測試環境配置(五) 一. 剝離硬件環境的設置 二. 靈活使用編譯開關 三. 導入修改后的bdf文件 四. 自動生成底層樁函數 五. 開始跑集成測試用例 六…

大模型(一)什么是 MCP?如何使用 Charry Studio 集成 MCP?

目錄一、什么是 MCP&#xff1f;1.1 &#x1f914; 開始之前的思考1.2 MCP 的定義1.3 MCP 結構二、MCP 的使用2.1 uv 的安裝2.2 MCP 廣場2.3 MCP 的配置2.4 MCP 的依賴安裝2.5 Charry Studio2.6 測試結果背景&#xff1a; MCP 這個概念大概是 2025 年上半年火起來的&#xff0c…

源碼導航頁

一、Python捕捉動作發送到Unity驅動模型跟著動&#xff08;獲取源碼&#xff09; 二、AI輸入法源碼&#xff08;獲取源碼&#xff09; 三、Java企業級后臺管理系統-登錄授權角色菜單&#xff08;獲取源碼&#xff09; 四、Jetson實現純視覺導航&#xff08;獲取源碼&#xff09…

HTTP/2 性能提升的核心原因

一、協議架構優化??二進制分幀&#xff08;Binary Framing&#xff09;?HTTP/2 將傳統文本格式的報文&#xff08;如請求頭、數據體&#xff09;拆分為獨立的二進制幀&#xff08;Frame&#xff09;&#xff0c;每個幀包含流標識符&#xff08;Stream ID&#xff09;&#x…

vulnhub-billu_b0x靶機滲透

一、靶場詳情 Billu_b0x 是 Vulnhub 上的經典中等難度靶機&#xff0c;主要考察從信息收集到提權的完整滲透流程&#xff1a;先通過端口和目錄掃描發現網站入口&#xff0c;利用 SQL 注入或文件包含進入后臺并上傳 WebShell&#xff0c;再通過反彈 Shell 獲取低權限用戶&#…

C# 相機內存復用(減少圖像采集耗時)以及行數復用

背景我們在做圖像處理時&#xff0c;都會對一些相機的SDK進行開發完成圖像采集的操作&#xff0c;為后續圖像處理做準備。本文主要的目的是降低圖像采集的耗時&#xff0c;應用在一些高速檢測的場景下。利用循環隊列內存復用的方式&#xff0c;去掉或者減少新建內存的時間。線掃…

MTK Linux DRM分析(十三)- Mediatek KMS實現mtk_drm_drv.c(Part.1)

一、簡介 MediaTek (MTK) 的DRM驅動(基于mtk_drm_drv.c)是為MediaTek SoC(如MT6985、MT6895等)設計的顯示子系統(Display Subsystem)驅動程序。它實現了Linux DRM/KMS框架,支持多CRTC、多平面(plane)、連接器(connector)和編碼器(encoder)的顯示管道。驅動處理硬…

Wireshark筆記-DHCP流程與數據包解析

背景DHCP從大學上網絡課時就開始知道了&#xff0c;當時只知道&#xff0c;能讓計算機上網&#xff0c;要不就靜態配IP&#xff0c;要不就DHCP獲取&#xff0c;就能上網。2021年時&#xff0c;畢業好幾年了&#xff0c;想學習下網絡知識&#xff0c;就準備考一個軟考網工。按要…

Coze用戶賬號設置修改用戶頭像-前端源碼

概述 Coze Studio的用戶頭像修改功能是用戶賬號設置中的重要組成部分&#xff0c;允許用戶上傳和更新個人頭像。本文將深入分析該功能的前端實現&#xff0c;包括組件架構、文件上傳處理、API設計和用戶體驗優化等方面。 技術架構 整體架構設計 Coze Studio采用現代化的前端架構…

新手Github提交PR(Pull requests)詳細教程

一、什么是Pull requests&#xff1f; Pull Requests&#xff08;PR&#xff09;是代碼協作平臺&#xff08;如 GitHub、GitLab 等&#xff09;中的一種功能&#xff0c;用于提議將某分支的代碼變更合并到另一個分支&#xff08;通常是主分支&#xff09;。它允許開發者在合并…

本地通過跳板機連接無公網IP的內網服務器

本地環境&#xff1a;SSH client 堡壘機&#xff1a;有公網IP&#xff0c;有連接內網服務器的秘鑰 SSH配置&#xff1a; Host jmsHostName [堡壘機的公網IP]Port 22User rootIdentityFile ~/.ssh/id_rsaHost appHostName 10.0.0.14Port 22User rootIdentityFile ~/.ssh/svc-p…

B樹,B+樹,B*樹

下面我們來詳細講解一下 B樹、B樹、B*樹 這三種非常重要的多路平衡查找樹。它們在數據庫和文件系統中有著極其廣泛的應用。一、為什么需要這些樹結構&#xff1f;在開始之前&#xff0c;我們先思考一個問題&#xff1a;為什么已經有了二叉搜索樹&#xff08;BST&#xff09;、A…

汽車零部件工廠ESOP系統工業一體機如何選型

在汽車零部件工廠的生產管理中&#xff0c;ESOP 系統發揮著至關重要的作用。而工業一體機作為 ESOP 系統的關鍵硬件支撐&#xff0c;其選型的合理性直接關系到生產效率的提升、生產過程的精準控制以及生產數據的可靠采集與分析。因此&#xff0c;為汽車零部件工廠選擇一款適合的…

?維基框架 (Wiki Framework) 1.1.0 版本發布? 提供多模型AI輔助開發

介紹 多模型AI輔助開發? 維基框架1.1.0集成了主流AI引擎的統一接口&#xff0c;支持開發者按需調用不同模型的優勢能力&#xff1a; ?DeepSeek?&#xff1a;專注代碼生成與重構&#xff0c;擅長復雜業務邏輯實現 ?ChatGPT?&#xff1a;多模態推理能力&#xff0c;適用于…

LabVIEW調用MATLAB 的分形生成

LabVIEW 調用 MATLAB&#xff0c;可借前者可視化流程與硬件交互優勢&#xff0c;結合后者強數值計算、算法能力&#xff0c;復用成熟算法提速開發&#xff0c;還能靈活改代碼。但需匹配版本、裝運行環境&#xff0c;數據傳遞有性能損耗&#xff0c;腳本出錯需跨軟件調試。?優點…