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