Vue3中的pinia使用方法總結(jié)(建議收藏版)
1.pinia介紹
pinia 是 Vue 的存儲庫,它允許您跨組件/頁面共享狀態(tài)。就是和vuex一樣的實現(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 項目,建議使用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)建容器掛載到根實例上
//引入stores暴露出的pinia的實例
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'
// 因為是個方法,所以我們得調(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實例
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實例
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)前這這個模塊的實例

這樣就在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>
就這樣可以啦!?。?/p>
是不是比vuex簡潔很多。。。
6.數(shù)據(jù)的持久化
pinia支持?jǐn)U展插件
我們想實現(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實現(xiàn)后臺系統(tǒng)權(quán)限控制的示例代碼
本篇文章主要介紹了基于Vue實現(xiàn)后臺系統(tǒng)權(quán)限控制的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
vue template中slot-scope/scope的使用方法
今天小編就為大家分享一篇vue template中slot-scope/scope的使用方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
Vue + AnimeJS實現(xiàn)3d輪播圖的詳細(xì)代碼
輪播圖在開發(fā)中是經(jīng)常用到的,3D輪播圖是其中最常用的一種,所以在這篇文章中將給大家介紹Vue + AnimeJS實現(xiàn)3d輪播圖,文中有詳細(xì)的代碼示例供大家參考,具有一定的參考價值,需要的朋友可以參考下2024-01-01
Vue3報錯‘defineProps‘?is?not?defined的解決方法
最近工作中遇到vue3中使用defineProps中報錯,飄紅,所以這篇文章主要給大家介紹了關(guān)于Vue3報錯‘defineProps‘?is?not?defined的解決方法,需要的朋友可以參考下2023-01-01

