Vue3中的pinia使用方法總結(jié)(建議收藏版)
1.pinia介紹
pinia 是 Vue 的存儲庫,它允許您跨組件/頁面共享狀態(tài)。就是和vuex一樣的實(shí)現(xiàn)數(shù)據(jù)共享。
依據(jù)Pinia官方文檔,Pinia是2019年由vue.js官方成員重新設(shè)計的新一代狀態(tài)管理器,更替Vuex4成為Vuex5。
Pinia 目前也已經(jīng)是 vue 官方正式的狀態(tài)庫。適用于 vue2 和 vue3??梢院唵蔚睦斫獬?Pinia 就是 Vuex5。也就是說, Vue3 項(xiàng)目,建議使用Pinia。
Pinia 的優(yōu)點(diǎn)
- pinia 符合直覺,易于學(xué)習(xí)。
- pinia 是輕量級狀態(tài)管理工具,大小只有1KB.
- pinia 模塊化設(shè)計,方便拆分。
- pinia 沒有 mutations,直接在 actions 中操作 state,通過 this.xxx 訪問響應(yīng)的狀態(tài),盡管可 以直接操作 state,但是還是推薦在 actions 中操作,保證狀態(tài)不被意外的改變。
- store 的 action 被調(diào)度為常規(guī)的函數(shù)調(diào)用,而不是使用 dispatch 方法或者是 MapAction 輔助函數(shù),這是在 Vuex 中很常見的。
- 支持多個 store。
- 支持 Vue devtools、SSR、webpack 代碼拆分。
更多查看文檔…
2.pinia基本使用
1.首先先安裝依賴
npm install pinia
2.在main.js中引入pinia并創(chuàng)建容器掛載到根實(shí)例上
//引入stores暴露出的pinia的實(shí)例 import pinia from './stores' createApp(App).use(pinia).mount('#app')
3.創(chuàng)建stores文件夾和index.js文件(這個文件以后基本不用管了)
import { createPinia } from "pinia"; const pinia = createPinia() export default pinia
4.在stores文件夾下創(chuàng)建counter.js文件。這個文件就是存有關(guān)counter相關(guān)的數(shù)據(jù)。(類似vuex的模塊化)
defineStore 是需要傳參數(shù)的,
- 第一個參數(shù)是id,就是一個唯一的值,簡單點(diǎn)說就可以理解成是一個命名空間.
- 第二個參數(shù)就是一個對象,里面有三個模塊需要處理,第一個是 state,第二個是 getters,第三個是 actions。
//定義關(guān)于counter的store import {defineStore} from 'pinia' /*defineStore 是需要傳參數(shù)的,其中第一個參數(shù)是id,就是一個唯一的值, 簡單點(diǎn)說就可以理解成是一個命名空間. 第二個參數(shù)就是一個對象,里面有三個模塊需要處理,第一個是 state, 第二個是 getters,第三個是 actions。 */ const useCounter = defineStore("counter",{ state:() => ({ count:66, }), getters: { }, actions: { } }) //暴露這個useCounter模塊 export default useCounter
注意:返回的函數(shù)統(tǒng)一使用useXXX作為命名方案,這是約定的規(guī)矩。例如上面的useCounter
5.然后再組件中使用:
<template> <!-- 在頁面中直接使用就可以了 不用 .state--> <div>展示pinia的counter的count值:{{counterStore.count}}</div> </template> <script setup> // 首先需要引入一下我們剛剛創(chuàng)建的store import useCounter from '../stores/counter' // 因?yàn)槭莻€方法,所以我們得調(diào)用一下 const counterStore = useCounter() </script>
注意:在模板使用 ,不用和vuex一樣還要.state,直接點(diǎn)state里面的K
運(yùn)行效果: 可以用vue3的調(diào)試工具看pinia
2.1注意Store獲取到后不能解構(gòu),否則失去響應(yīng)式
案例需求,點(diǎn)擊按鈕加一:
一個不解構(gòu),一個不解構(gòu)看看區(qū)別。
<template> <div>展示pinia的counter的count值:{{counterStore.count}}</div> <div>展示解構(gòu)出來的pinia的counter的count值:{{count}}</div> <button @click="addCount">count+1</button> </template> <script setup> import useCounter from '../stores/counter' const counterStore = useCounter() const {count} = counterStore function addCount(){ //這里可以直接操作count,這就是pinia好處,在vuex還要commit在mutaitions修改數(shù)據(jù) counterStore.count++ } <script/>
在 vuex 里面是堅決不允許這樣子直接操作 state 數(shù)據(jù)的,pinia是可以的,看看上面的addCount函數(shù)直接操作。
運(yùn)行結(jié)果:
解決方案:
pinia提供了一個函數(shù)storeToRefs解決。引用官方API storeToRef 作用就是把結(jié)構(gòu)的數(shù)據(jù)使用ref做代理
import {storeToRefs} from 'pinia' const counterStore = useCounter() const {count} = storeToRefs(counterStore)
現(xiàn)在數(shù)據(jù)都是響應(yīng)式的了
3.修改state的數(shù)據(jù)
重新新建一個user模塊
stores/user.js
//定義一個關(guān)于user的store import {defineStore} from 'pinia' const useUser = defineStore("user",{ state:()=>({ name:"紫陌", age:18 }) }) export default useUser
組件中修改數(shù)據(jù):
**第一種方法:**點(diǎn)擊按鈕修改數(shù)據(jù),這種方法是最直接的修改數(shù)據(jù)
<template> <div> <h2>名字是:{{name}}</h2> <h2>年齡是:{{age}}</h2> <button @click="updateStore">修改Store數(shù)據(jù)</button> </div> </template> <script setup> import useUser from '../stores/user' import {storeToRefs} from 'pinia' const userStore = useUser() const {name,age} = storeToRefs(userStore) function updateStore(){ //一個個的修改狀態(tài) userStore.name = "zimo" userStore.age = 20 }
效果:點(diǎn)擊也修改了
第二種方法:$patch函數(shù)修改
function updateStore(){ //一個個的修改狀態(tài) // userStore.name = "zimo" // userStore.age = 20 // 一次性修改多個狀態(tài) userStore.$patch({ name:"zimo", age:20 }) }
這個方式也可以,效果一樣。
第三種方法:$state 方式(這個是替換的方式。)這個基本不用,這里就不多說??梢钥床殚單臋n。
第四種方法:$reset()函數(shù)是重置state數(shù)據(jù)的
新增一個重置按鈕:
function resetStore(){ userStore.$reset() }
運(yùn)行結(jié)果:點(diǎn)擊了修改數(shù)據(jù)按鈕之后在點(diǎn)重置按鈕就恢復(fù)原始的數(shù)據(jù)。
4.getters的使用
getters 類似于 vue 里面的計算屬性,可以對已有的數(shù)據(jù)進(jìn)行修飾。不管調(diào)用多少次,getters中的函數(shù)只會執(zhí)行一次,且都會緩存。
1.最基本的使用
在counter模塊演示了,counter模塊:
//定義關(guān)于counter的store import {defineStore} from 'pinia' const useCounter = defineStore("counter",{ state:() => ({ count:66, }), getters:{ //基本使用 doubleCount(state) { return state.count * 2 }, }, }) //暴露這個useCounter模塊 export default useCounter
組件中:
<div> <h1>getters的使用</h1> <h2>doubleCount:{{counterStore.doubleCount}}</h2> </div>
運(yùn)行效果:
這樣就是最基本的使用了。
2.一個getter引入另外一個getter
couter模塊:
getters:{ //基本使用 doubleCount(state) { return state.count * 2 }, //一個getter引入另外一個getter doubleCountAddTwo(){ console.log(this); //this.是store實(shí)例 return this.doubleCount + 2 } },
組件中使用:
<div> <h1>getters的使用</h1> <h2>doubleCount:{{counterStore.doubleCount}}</h2> <h2>doubleCountAddTwo:{{counterStore.doubleCountAddTwo}}</h2> </div>
運(yùn)行效果并且看看打印的this:
3.getters中用別的store中的數(shù)據(jù)
在counter模塊中拿user模塊的store數(shù)據(jù)。
count模塊:
//定義關(guān)于counter的store import {defineStore} from 'pinia' import useUser from "./user" const useCounter = defineStore("counter",{ state:() => ({ count:66, }), getters:{ //基本使用 doubleCount(state) { return state.count * 2 }, //一個getter引入另外一個getter doubleCountAddTwo(){ console.log(this); //this.是store實(shí)例 return this.doubleCount + 2 }, //getters中用別的store中的數(shù)據(jù) showMessage(state){ console.log(state); console.log(this) //獲取user信息,拿到useUser模塊 const userStore = useUser() //拼接信息 return `name:${userStore.name}--count:${state.count}` } }, }) //暴露這個useCounter模塊 export default useCounter
注意:要引入user模塊
組件中:
<div> <h1>getters的使用</h1> <h2>doubleCount:{{counterStore.doubleCount}}</h2> <h2>doubleCountAddTwo:{{counterStore.doubleCountAddTwo}}</h2> <h2>showMessage:{{counterStore.showMessage}}</h2> </div>
運(yùn)行結(jié)果:
注意:我打印了this和store,他們都是當(dāng)前這這個模塊的實(shí)例
這樣就在counter模塊拿到了user模塊的數(shù)據(jù)了。
5. actions的使用
actions 是可以處理同步,也可以處理異步,同步的話相對來說簡單一點(diǎn).actions類似methods
1.先看同步使用:
counter模塊使用:
在actions定義了兩個函數(shù)一個加一的函數(shù),一個加20的函數(shù)。
//定義關(guān)于counter的store import {defineStore} from 'pinia' const useCounter = defineStore("counter",{ state:() => ({ count:66, }), actions:{ increment(state){ //actions沒有state,只能通過this拿store,這里打印 console.log(state); this.count++ }, incrementNum(num){ this.count += num } } }) //暴露這個useCounter模塊 export default useCounter
組件中:
actions函數(shù)在組件中使用
<div> <h1>actions的使用</h1> <h2>count的事值:{{counterStore.count}}</h2> <button @click="changeState">count+1</button> <button @click="incrementNum">count+20</button> </div> <script setup> import useCounter from '../stores/counter' const counterStore = useCounter() function changeState(){ counterStore.increment() } function incrementNum(){ counterStore.incrementNum(20) } </script>
運(yùn)行結(jié)果并且看看state是什么
初始值是66,點(diǎn)了一次加1和點(diǎn)了一次加20
注意:state的結(jié)果是undefined 所以actions只能通過this訪問store。getter的話state和this都能訪問。
2.異步操作使用
在 actions 處理異步的時候呢,我們一般是與 async 和 await 連用。
counter模塊: 這里大致演示,具體還看自己怎么使用。
state:() => ({ count:66, list:[] }), actions:{ //大概演示這個異步流程 async axiosData(){ const res = await fetch("http://-----------------") if(code ==200){ //收到數(shù)據(jù)保存到store this.list = res.data.list return "ok" } } }
組件使用:
<template> <!-- 遍歷store的數(shù)據(jù) --> <div v-for="item in counterStore.list"></div> </template> <script setup> import useCounter from '../stores/counter' const counterStore = useCounter() counterStore.axiosData().then(res =>{ console.log("成功",res); }) </script>
就這樣可以啦?。?!
是不是比vuex簡潔很多。。。
6.數(shù)據(jù)的持久化
pinia支持?jǐn)U展插件
我們想實(shí)現(xiàn)數(shù)據(jù)持久化
npm i pinia-plugin-persist
export const useUserStore = defineStore({ state () { return { count: 0, num: 101, list: [1, 2, 3, 4 ] } }, persist: { enabled: true, // 開啟緩存 默認(rèn)會存儲在本地localstorage storage: sessionStorage, // 緩存使用方式 paths:[] // 需要緩存鍵 } })
效果:
總結(jié)
到此這篇關(guān)于Vue3中pinia使用的文章就介紹到這了,更多相關(guān)Vue3中pinia使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于Vue實(shí)現(xiàn)后臺系統(tǒng)權(quán)限控制的示例代碼
本篇文章主要介紹了基于Vue實(shí)現(xiàn)后臺系統(tǒng)權(quán)限控制的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08vue template中slot-scope/scope的使用方法
今天小編就為大家分享一篇vue template中slot-scope/scope的使用方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09vue中如何實(shí)現(xiàn)拖拽調(diào)整順序功能
這篇文章主要介紹了vue中如何實(shí)現(xiàn)拖拽調(diào)整順序功能問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05Vue + AnimeJS實(shí)現(xiàn)3d輪播圖的詳細(xì)代碼
輪播圖在開發(fā)中是經(jīng)常用到的,3D輪播圖是其中最常用的一種,所以在這篇文章中將給大家介紹Vue + AnimeJS實(shí)現(xiàn)3d輪播圖,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下2024-01-01Vue3報錯‘defineProps‘?is?not?defined的解決方法
最近工作中遇到vue3中使用defineProps中報錯,飄紅,所以這篇文章主要給大家介紹了關(guān)于Vue3報錯‘defineProps‘?is?not?defined的解決方法,需要的朋友可以參考下2023-01-01