前端數(shù)據(jù)存儲常用工具Vuex、Pinia、Redux詳解
前言:
前端數(shù)據(jù)存儲工具中,Vuex、Pinia和Redux存儲是常用工具,它們各自具有不同的特點和適用場景。
一、Vuex
1.安裝 Vuex
(1)使用 npm 或 yarn 安裝 Vuex
安裝:npm i vuex
yarn i vuex
2.創(chuàng)建 Store
(1)創(chuàng)建 store 文件夾和文件
在項目的 src
目錄下,創(chuàng)建一個名為 store
的文件夾。在 store
文件夾中,創(chuàng)建一個 index.js
文件。
(2)引入 Vuex 并創(chuàng)建 Store 實例
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); const store = new Vuex.Store({ // 數(shù)據(jù) state: { count: 0, }, // store的計算屬性 getters: {}, // 改變狀態(tài)的唯一方法 同步函數(shù) mutations: {}, // actions類似于mutation 可包含異步函數(shù) actions: {}, // Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter,甚至是嵌套子模塊。 modules: {} }) export default store;
3.在 Vue 實例中使用 Store
(1)在 main.js 中引入 Store
在項目的入口文件 main.js
中,引入剛才創(chuàng)建的 Store 實例,并將其傳遞給 Vue 構(gòu)造函數(shù)。
import Vue from 'vue' // 引入vue import App from './App.vue' // 引入App.vue import store from './store' new Vue({ router, store, render: h => h(App) }).$mount('#app')
4.在組件中使用 Vuex
(1)訪問狀態(tài)(State)
在組件中,可以通過 this.$store.state
訪問 Vuex 中的狀態(tài)。
export default { computed: { count() { return this.$store.state.count; } } }
(2)提交變更(Mutations)
在組件中,可以通過 this.$store.commit()
方法提交變更。
export default { methods: { increment() { this.$store.commit('increment'); } } }
(3)執(zhí)行異步操作(Actions)
在組件中,可以通過 this.$store.dispatch()
方法執(zhí)行異步操作。
export default { methods: { asyncIncrement() { this.$store.dispatch('asyncIncrement'); } } }
(4)使用 Getter
Getter 用于從 state 中派生出一些狀態(tài)。在組件中,可以通過 this.$store.getters
訪問 Getter。例如:
export default { computed: { doubleCount() { return this.$store.getters.doubleCount; } } }
二、Pinia
1.安裝Pinia
安裝:npm install pinia
2.定義Store
(1)在項目的src
目錄下創(chuàng)建一個stores
文件夾(如果尚未存在),用于存放多個Store文件。
(2)在stores
文件夾中創(chuàng)建一個新的Store文件,例如cart.js
。
(3)使用defineStore
函數(shù)來定義一個Store。需要指定Store的唯一名稱,并提供一個包含state
、getters
和actions
等屬性的對象來定義Store的內(nèi)容。
import { defineStore } from 'pinia'; export const useCartStore = defineStore('cart', { state: () => ({ cartList: [], // 購物車列表數(shù)組 // 其他狀態(tài)... }), getters: { allCount: (state) => state.cartList.reduce((total, goods) => total + goods.count, 0), // 計算所有商品的總數(shù)量 allPrice: (state) => state.cartList.reduce((total, goods) => total + goods.price * goods.count, 0), // 計算所有商品的總價格 // 其他getter... }, actions: { addCart(goods) { // 添加商品到購物車的邏輯 }, deleteCart(goodsId) { // 刪除購物車中商品的邏輯 }, // 其他action... }, });
3.使用Store
(1)在需要使用Store的Vue組件中,通過import
語句導入相應的Store函數(shù)。
(2)使用Store函數(shù)來獲取Store實例,并通過這個實例訪問狀態(tài)數(shù)據(jù)或調(diào)用方法。
<template> <!-- 使用Store中的數(shù)據(jù) --> <div>購物車商品總數(shù):{{ cartStore.allCount }}</div> </template> <script setup> import { useCartStore } from '@/stores/cart'; const cartStore = useCartStore(); // 可以通過cartStore訪問狀態(tài)數(shù)據(jù)或調(diào)用方法 </script>
4.數(shù)據(jù)持久化
(1)如果希望在頁面刷新或關(guān)閉后仍能保留Store中的數(shù)據(jù),可以使用pinia-plugin-persistedstate
插件來實現(xiàn)數(shù)據(jù)持久化。
(2)安裝插件
運行命令:
npm install pinia-plugin-persistedstate
(3)在項目的入口文件(如main.js
或main.ts
)中,導入并使用該插件。
import { createApp } from 'vue'; import { createPinia } from 'pinia'; import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'; import App from './App.vue'; const app = createApp(App); const pinia = createPinia(); pinia.use(piniaPluginPersistedstate); // 使用持久化插件 app.use(pinia); app.mount('#app');
(4)在定義Store時,通過傳入{ persist: true }
選項來啟用持久化功能。
export const useCartStore = defineStore('cart', { // ...state, getters, actions等定義 }, { persist: true }); // 啟用持久化
三、Redux
state:存儲應用的狀態(tài)。
action:表示狀態(tài)變化的對象。
reducer:純函數(shù),用于根據(jù)action更新狀態(tài)。
middleware:中間件,用于處理異步邏輯和副作用。
1.安裝依賴
在項目的根目錄下,運行npm install redux react-redux @reduxjs/toolkit
命令來安裝Redux及其相關(guān)依賴。
安裝:npm install redux
2.創(chuàng)建Store
(1)在項目的src
目錄下創(chuàng)建一個store
文件夾(如果尚未存在),用于存放Store相關(guān)的文件。
(2)在store
文件夾中創(chuàng)建一個index.js
文件,用于組合所有子模塊的Store,并導出全局Store。
(3)在store
文件夾中創(chuàng)建一個modules
文件夾,用于存放多個子Store模塊。
(4)在modules
文件夾中創(chuàng)建具體的子Store模塊文件,例如counterStore.js
。
3.編寫Redux配置
(1)在子Store模塊文件中,使用createSlice
函數(shù)創(chuàng)建存儲對象。需要傳入一個配置對象,包括name
(指定存儲器名稱)、initialState
(指定初始化數(shù)據(jù))和reducers
(指定修改數(shù)據(jù)的方法)。
(2)導出操作數(shù)據(jù)的行為函數(shù)(actions)和reducer函數(shù)。
(3)在store/index.js
文件中,使用configureStore
函數(shù)將所有子模塊的Store組合在一起,并導出全局Store。
4.在React組件中使用全局Store
(1)在項目的入口文件(如index.js
或App.js
)中,使用Provider
組件將全局Store注入到React應用中。
(2)在需要使用全局狀態(tài)的React組件中,使用useSelector
函數(shù)從Store中讀取狀態(tài)數(shù)據(jù)。
(3)使用useDispatch
函數(shù)獲取dispatch方法,通過執(zhí)行操作狀態(tài)函數(shù)(actions)并傳入?yún)?shù)來創(chuàng)建action對象,然后使用dispatch方法提交action以修改狀態(tài)。
具體示例
以下是一個簡單的Redux使用示例,包括創(chuàng)建Store、定義actions和reducer、在React組件中使用Store等步驟:
// store/modules/counterStore.js
import { createSlice } from "@reduxjs/toolkit"; const counterStore = createSlice({ name: "counter", initialState: { count: 0 }, reducers: { increment(state) { state.count++; }, decrement(state) { state.count--; }, addToNum(state, action) { state.count = state.count + action.payload; }, }, }); export const { increment, decrement, addToNum } = counterStore.actions; export default counterStore.reducer;
// store/index.js
import { configureStore } from "@reduxjs/toolkit"; import counterReducer from "./modules/counterStore"; const store = configureStore({ reducer: { counter: counterReducer, }, }); export default store;
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import store from "./store"; import { Provider } from "react-redux"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <Provider store={store}> <App /> </Provider> );
import { useSelector, useDispatch } from "react-redux"; import { increment, addToNum } from "./store/modules/counterStore"; export default function App() { const { count } = useSelector((state) => state.counter); const dispatch = useDispatch(); function countIncrement() { dispatch(increment()); } function add20() { dispatch(addToNum(20)); } return ( <div> <div>{count}</div> <button onClick={countIncrement}>+1</button> <button onClick={add20}>+20</button> </div> ); }
注意事項
Redux中的狀態(tài)是單向流動的,只能通過dispatch action來更新狀態(tài),不能直接修改狀態(tài)。
使用Redux Toolkit可以簡化Redux的配置和管理,推薦在新項目中使用。
在React組件中使用Redux時,要確保正確連接Store和組件,以能夠讀取和更新狀態(tài)。
四、總結(jié)
Vuex | Pinia | Redux | |
---|---|---|---|
適用框架 | Vue.js | Vue.js(特別是Vue 3) | 跨框架(常用于React,但也適用于Vue.js等) |
設計理念 | 為Vue.js設計,提供全局狀態(tài)管理 | Vuex的升級版,基于Vue 3的Composition API設計 | 獨立的狀態(tài)管理庫,遵循單項數(shù)據(jù)流原則 |
核心概念 | Store、state、mutations、actions、getters、modules | Store、state、getters、actions | Store、state、action、reducer、middleware、store enhancer |
狀態(tài)修改方式 | 使用mutations進行同步修改,actions處理異步邏輯 | 使用actions直接修改狀態(tài),actions支持異步操作 | 通過action觸發(fā)reducer進行純函數(shù)式的狀態(tài)更新 |
API復雜度 | API豐富,功能全面,但相對復雜 | API簡潔,易于使用,與Vue 3的Composition API緊密結(jié)合 | API較為抽象,需要理解單向數(shù)據(jù)流和純函數(shù)的概念 |
異步處理 | 通過actions調(diào)用mutations實現(xiàn) | actions直接支持異步操作 | 通過中間件(如redux-thunk、redux-saga)處理異步邏輯 |
插件和擴展 | 提供插件系統(tǒng),可以擴展功能 | 可以通過插件擴展功能,生態(tài)逐漸完善 | 依賴第三方中間件和庫進行擴展 |
持久化存儲 | 可以使用插件(如vuex-persistedstate)實現(xiàn) | 可以使用插件(如pinia-plugin-persistedstate)實現(xiàn) | 可以使用redux-persist實現(xiàn)持久化存儲 |
開發(fā)者工具 | 提供官方開發(fā)者工具,方便調(diào)試和監(jiān)控狀態(tài)變化 | 提供官方開發(fā)者工具,支持Vue Devtools | 提供強大的開發(fā)者工具,如Redux DevTools |
學習曲線 | 對于Vue.js開發(fā)者較為友好,但概念較多,學習曲線較陡 | API簡潔,易于上手,適合Vue 3項目 | 需要理解單向數(shù)據(jù)流和純函數(shù)的概念,學習曲線較陡 |
適用場景 | 適用于Vue.js項目,特別是中小型項目 | 適用于Vue 3項目,提供簡潔的狀態(tài)管理解決方案 | 適用于需要復雜狀態(tài)管理和異步處理的大型應用,跨框架使用 |
總結(jié)
到此這篇關(guān)于前端數(shù)據(jù)存儲常用工具Vuex、Pinia、Redux的文章就介紹到這了,更多相關(guān)前端數(shù)據(jù)存儲Vuex、Pinia、Redux內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vuex state及mapState的基礎(chǔ)用法詳解
這篇文章主要介紹了vuex state及mapState的基礎(chǔ)用法詳解,本文通過實例代碼相結(jié)合的形式給大家介紹的非常詳細,需要的朋友跟隨腳本之家小編一起學習吧2018-04-04element-ui循環(huán)顯示radio控件信息的方法
今天小編就為大家分享一篇element-ui循環(huán)顯示radio控件信息的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08vue3+echarts實現(xiàn)好看的圓角環(huán)形圖
這篇文章主要介紹了vue3+echarts實現(xiàn)好看的圓角環(huán)形圖效果,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10