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

