Vue使用Pinia輕松實(shí)現(xiàn)狀態(tài)管理
前言
pinia,一個(gè)基于Vue3的狀態(tài)管理庫(kù),它可以幫助開發(fā)人員管理Vue應(yīng)用程序的狀態(tài),Pinia使用Vue3的Composition API提供了更簡(jiǎn)單,靈活的狀態(tài)管理方式,通過(guò)創(chuàng)建store來(lái)管理應(yīng)用程序的狀態(tài),還提供了插件和工具來(lái)幫助開發(fā)人員更輕松的使用它。
Pinia對(duì)比VueX
之前我們?cè)趘ue2的時(shí)候使用的狀態(tài)管理庫(kù)是VueX,在Vue3中想使用VueX,需要使用到VueX4版本,而在Vue3組合式API下設(shè)計(jì)了全新的狀態(tài)管理庫(kù):Vuex5,也就是Pinia(已經(jīng)被納入官方了)
那Pinia相比VueX有什么優(yōu)勢(shì)呢?
在當(dāng)時(shí)pinia的作者就作出了這么一個(gè)提案:
- pinia都支持在vue2和vue3中使用
- 在vuex想修改數(shù)據(jù)狀態(tài)需要mutations,而pinia去掉了mutations,只有state,getters和actions。修改數(shù)據(jù)狀態(tài)直接在actions里操作,pinia推崇使用類似于 JavaScript 對(duì)象的方式來(lái)更新狀態(tài),即直接對(duì) state 進(jìn)行修改,可以減少代碼量,并且降低了出錯(cuò)的可能性
- pinia中沒(méi)有嵌套模塊,在vuex中我們可能會(huì)用到大量的模塊,一層套一層,使?fàn)顟B(tài)管理變得復(fù)雜,也有可能會(huì)造成命名沖突,在Composition API下pinia中可以定義多個(gè)store,然后將多個(gè)store組合在一起,變得更加靈活
- 完整的TypeScript支持,vuex對(duì)ts的類型檢查,類型推斷和泛型的支持都不太友好,模塊命名空間的支持也不夠完善
除此之外兩者的api都是相同的,使用的方式也是相同的,關(guān)于vuex的使用可以看看之前寫的vuex文章
Pinia的使用
安裝pinia
使用pinia需要先安裝,可以通過(guò)yarn或者npm安裝
yarn add pinia
# or with npm
npm install pinia
在vue2中使用,你還需要安裝一個(gè)插件并pinia
在應(yīng)用程序的根目錄注入創(chuàng)建的,如果vue版本<2.7,還需要安裝 composition api: @vue/composition-api
安裝完之后在入口文件引入pinia的createPinia方法并調(diào)用得到pinia的實(shí)例,然后掛載到vue實(shí)例上
import { createApp } from "vue"; import App from "./App.vue"; import { createPinia } from "pinia"; //創(chuàng)建pinia實(shí)例 const pinia = createPinia(); const app = createApp(App); //掛載到vue實(shí)例上 app.use(pinia); app.mount("#app");
定義store容器
在src目錄下創(chuàng)建store目錄來(lái)存放pinia容器相關(guān)代碼,在里面新建了一個(gè)index.ts文件,在index.ts文件里首先要定義一個(gè)容器,定義容器使用defineStore
來(lái)定義,主要接收兩個(gè)參數(shù),一個(gè)是容器的名字(唯一),另一個(gè)是容器的對(duì)象,最后將容器導(dǎo)出,就可以在組件中使用了
import { defineStore } from "pinia"; export const useTestStore = defineStore("test", { /** * 類似組件中的data,存儲(chǔ)全局狀態(tài) * 必須是箭頭函數(shù),避免數(shù)據(jù)狀態(tài)污染 */ state: () => { return { message: "hello world", count:0, }; }, /** * 類似組件中的computed */ getters: {}, /** * 類似組件中的methods,封裝業(yè)務(wù)邏輯,修改state */ actions: {}, });
在組件中導(dǎo)入并使用容器
state的使用
在組件中導(dǎo)入容器并且調(diào)用,得到容器的實(shí)例,就可以直接使用state里的數(shù)據(jù)或者在模板中展示
<script setup lang="ts"> import { useTestStore } from "./store"; const store = useTestStore(); </script> <template> <div>{{ store.message }}</div> </template> <style scoped> </style>
也可以使用解構(gòu)
的方式拿到和使用數(shù)據(jù),但是這樣拿到的數(shù)據(jù)不是響應(yīng)式
的,修改的時(shí)候頁(yè)面上是不會(huì)發(fā)生變化的
<script setup lang="ts"> import { useTestStore } from "./store"; const store = useTestStore(); //解構(gòu)state const { message, count } = store; const countAdd = () => { store.count++; }; </script> <template> <div> <div>{{ store.message }}</div> <div>{{ store.count }}</div> <hr /> <div>{{ "解構(gòu)后:" + message }}</div> <div>{{ "解構(gòu)后:" + count }}</div> <button @click="countAdd">count++</button> </div> </template> <style scoped> </style>
針對(duì)這種情況解決的辦法就是解構(gòu)的時(shí)候使用pinia的storeToRefs
方法將實(shí)例包裹住,state里的數(shù)據(jù)就變成響應(yīng)式的了
import { storeToRefs } from "pinia"; //解構(gòu)state,對(duì)state里的數(shù)據(jù)做了reactive處理 const { message, count } = storeToRefs(store);
狀態(tài)的更新和actions的使用
在組件里修改state的狀態(tài)的時(shí)候有三種方式:
- 直接修改
- $patch直接修改
- $patch通過(guò)函數(shù)修改
const countAdd = () => { // 直接修改 store.count++; store.message = 'hello pinia' // 修改多個(gè)數(shù)據(jù) $patch批量修改 store.$patch({ count: store.count + 1, message: "hello pinia", }); // $patch 函數(shù)(推薦) store.$patch(state=>{ state.count++ state.message = "hello pinia" }) };
也可以通過(guò)actions
處理,在actions定義一個(gè)方法,通過(guò)this
訪問(wèn)當(dāng)前實(shí)例拿到state里的數(shù)據(jù),就像vue2的options API一樣在methods里拿data里的數(shù)據(jù)
// store actions: { handleChangeState() { this.message = "hello pinia"; this.count++; }, }, //component const countAdd = () => { store.handleChangeState(); };
也可以在調(diào)用actions里的方法的時(shí)候傳遞參數(shù)
// store actions: { handleChangeState(num?: number) { this.count += num ?? 0; }, }, //component const countAdd = () => { store.handleChangeState(10); };
getters的使用
getters類似組件中的computed,接收一個(gè)state參數(shù),這個(gè)state就是容器里的state狀態(tài)對(duì)象,當(dāng)依賴的state發(fā)生變化的時(shí)候pinia就會(huì)自動(dòng)更新getters的值,而且getters具有默認(rèn)的緩存機(jī)制
如果一個(gè)getter所依賴的state沒(méi)有發(fā)生變化,那么就返回上一次計(jì)算的結(jié)果,而不會(huì)重新計(jì)算,顯著提高了性能
// getters getters: { // typescript自動(dòng)推導(dǎo)返回值類型 countMUL10(state) { console.log("getter被調(diào)用了"); return state.count * 10; }, // or手動(dòng)指定返回值類型 countMUL10():number { console.log("getter被調(diào)用了"); return this.count * 10; }, }, //component <template> <div> <div>{{ store.count }}</div> // 調(diào)用多次 <div>{{ store.countMUL10 }}</div> <div>{{ store.countMUL10 }}</div> <div>{{ store.countMUL10 }}</div> <button @click="countAdd">count++</button> </div> </template>
store容器調(diào)用另一個(gè)store容器
如果你想在一個(gè)Store中使用另一個(gè)Store,就和在組件中使用store一樣操作就可以了
import { defineStore } from "pinia"; //導(dǎo)入一個(gè)store容器 import { useTestStore } from "."; export const useLoginStore = defineStore("login", { state: () => { return {}; }, getters: {}, actions: { handlerOtherStore() { //得到store實(shí)例,調(diào)用實(shí)例里的方法 const testStore = useTestStore(); testStore.handleChangeState(10); }, }, });
以上就是Vue使用Pinia輕松實(shí)現(xiàn)狀態(tài)管理的詳細(xì)內(nèi)容,更多關(guān)于Vue Pinia的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue webpack打包后圖片路徑錯(cuò)誤的完美解決方法
這篇文章主要介紹了vue webpack打包后圖片路徑錯(cuò)誤的解決方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-12-12Vue加載組件、動(dòng)態(tài)加載組件的幾種方式
組件是Vue.js最強(qiáng)大的功能之一。組件可以擴(kuò)展HTML元素,封裝可重用的代碼。這篇文章通過(guò)實(shí)例代碼給大家介紹了Vue加載組件、動(dòng)態(tài)加載組件的幾種方式,需要的朋友參考下吧2018-08-08Vue實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁(yè)計(jì)算器
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁(yè)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04vue element實(shí)現(xiàn)多個(gè)Formt表單同時(shí)驗(yàn)證
這篇文章主要介紹了vue element實(shí)現(xiàn)多個(gè)Formt表單同時(shí)驗(yàn)證方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06vue3.x源碼剖析之?dāng)?shù)據(jù)響應(yīng)式的深入講解
這篇文章主要給大家介紹了關(guān)于vue3.x源碼剖析之?dāng)?shù)據(jù)響應(yīng)式的相關(guān)資料,在講解過(guò)程中,我們會(huì)對(duì)比Vue2.x的API特性,使用有哪些區(qū)別,需要的朋友可以參考下2022-01-01詳解vue渲染從后臺(tái)獲取的json數(shù)據(jù)
這篇文章主要介紹了詳解vue渲染從后臺(tái)獲取的json數(shù)據(jù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07vue單頁(yè)應(yīng)用加百度統(tǒng)計(jì)代碼(親測(cè)有效)
這篇文章主要介紹了vue單頁(yè)應(yīng)用加百度統(tǒng)計(jì)代碼的解決方法,需要的朋友參考下吧2018-01-01淺談vue實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽的函數(shù) Object.defineProperty
本篇文章主要介紹了淺談vue實(shí)現(xiàn)數(shù)據(jù)監(jiān)聽的函數(shù) Object.defineProperty,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06