Vue3之狀態(tài)管理器(Pinia)詳解及使用方式
注意:本文項(xiàng)目使用腳手架為 Vite;
1. 前言
Pinia 對(duì)比 Vuex
- Pinia 同時(shí)支持 Vue2 以及 Vue3 ,這讓同時(shí)使用兩個(gè)版本的小伙伴更容易上手;
- Pinia 中只存在 State,getter,action,剔除掉了 Vuex 中的 Mutation 及 Module;
- Pinia 中的 action 可同時(shí)支持同步任務(wù)、異步任務(wù);
- 更友好的支持了 TypeScript ,無(wú)需創(chuàng)建自定義復(fù)雜包裝器來(lái)支持 TypeScript,所有內(nèi)容都是類型化的,并且 API 的設(shè)計(jì)方式盡可能利用 TS 類型推斷;
- Pinia 在修改狀態(tài)的時(shí)候不需要通過(guò)其他 api,如:vuex 需通過(guò) commit,dispatch 來(lái)修改,所以在語(yǔ)法上比 vuex 更容易理解和使用靈活;
- 由于去除掉了 Module ,無(wú)需再創(chuàng)建各個(gè)模塊嵌套了。Vuex 中,如果數(shù)據(jù)過(guò)多,通常會(huì)通過(guò)劃分模塊來(lái)進(jìn)行管理,而 Pinia 中,每個(gè) Store 都是獨(dú)立的,互不影響;
- 支持服務(wù)端渲染;
2. 安裝及引入
yarn add pinia // 或者使用 npm npm install pinia
安裝完 Pinia 包之后,需要在 main.js 文件中導(dǎo)入 createPinia 函數(shù)并將 Pinia 插件與 Vue 應(yīng)用程序綁定:
import { createApp } from 'vue'; import App from './App.vue'; // 引入 createPinia 函數(shù) import { createPinia } from 'pinia'; const app = createApp(App) // 使用 createPinia() 來(lái)創(chuàng)建 Pinia(根存儲(chǔ)),并應(yīng)用到整個(gè)應(yīng)用中 app.use(createPinia()); app.mount('#app');
使用 createPinia() 函數(shù)創(chuàng)建并初始化 Pinia 插件實(shí)例,將其與 Vue 應(yīng)用程序綁定使用 app.use(pinia)。
至此,我們就可以使用Pinia 來(lái)管理 Vue 應(yīng)用程序的狀態(tài)了。
最后,在 src 文件下創(chuàng)建一個(gè) store 文件夾,并添加 store.js 文件。
3. Pinia的使用Store
Store
是使用 defineStore() 定義的,并且它需要一個(gè)唯一名稱,作為第一個(gè)參數(shù)傳遞。
這個(gè)名字 ,也被用作 id 是必須傳入的, Pinia 將用它來(lái)連接 store 和 devtools。
將返回的函數(shù)命名為 use… 是跨可組合項(xiàng)的約定,以使其符合使用習(xí)慣。
State
State 是 store 中存儲(chǔ)數(shù)據(jù)的地方。
通過(guò)定義 State,可以在 store 的任何位置訪問(wèn)和修改數(shù)據(jù)。
// store/store.js import { defineStore } from 'pinia'; export const useMainStore = defineStore('main',{ state: () => { return { count:0 } } })
// views/home.vue <template> <div class="count">state:{{mainStore.count}}</div> <div class="btnWrap"> <button @click="resetStore">重 置</button> </div> </template> <script setup> import {useMainStore} from '@/store/store.js'; const mainStore = useMainStore(); console.log(mainStore.count) // 0 const resetStore = () => { mainStore.$reset() } </script>
效果:
Getters
Getter 用來(lái)獲取從 state 派生的數(shù)據(jù),類似于 Vue 組件中的 computed 計(jì)算屬性。
可通過(guò) defineStore() 中的 getters 屬性來(lái)定義它們。
推薦使用箭頭函數(shù),并且它將接收 state 作為第一個(gè)參數(shù):
export const useStore = defineStore('main', { state: () => ({ count: 0, }), getters: { doubleCount: (state) => state.count * 2, }, })
Actions
Action 相當(dāng)于組件中的方法。
它可以通過(guò) defineStore() 中的 actions 屬性來(lái)定義;
Action 是一種將異步操作封裝在 store 中的方式,它是一個(gè)可被調(diào)用的函數(shù),也可接收參數(shù)并修改 store 中的狀態(tài)。
import { defineStore } from 'pinia' export const myStore = defineStore('myStore',{ state: () => ({ message: 'Hello', }), actions: { async fetchMessage() { const res = await fetch('http://127.0.0.1:5173/message') this.message = res.message }, }, })
4. 示例完整代碼
4.1 選項(xiàng)式寫(xiě)法
// store/store.js import { defineStore } from 'pinia'; import axios from 'axios'; export const useMainStore = defineStore('main',{ state: () => { return { count:0, count2:0, list:[], } }, getters:{ doubleCount(){ return this.count*2; } }, actions:{ add(){ this.count++; }, update(val){ this.count = val.value; }, add2(){ this.count2++; }, // 異步 async getList(){ const res = await axios.get('https://api.oioweb.cn/api/common/history'); if(res.data.code == 200){ this.list = res.data.result || []; } }, } })
在組件中使用
<template> <div class="count">state:{{mainStore.count}}</div> <div class="count">getters:{{mainStore.doubleCount}}</div> <div class="btnWrap"> <button @click="resetStore">重 置</button> <button @click="addCount">增 加</button> <button @click="updateCount">更新至100</button> </div> <hr/> <div class="count">state:{{count2}}</div> <div class="btnWrap"> <button @click="add2">增 加</button> </div> <hr/> <h3>歷史上的今天</h3> <ul class="list"> <li v-for="(item,index) in mainStore.list" :key="index"> {{item.year}}年 - {{item.title}} </li> </ul> </template>
<script setup> import {useMainStore} from '@/store/store.js'; import {onMounted,ref} from 'vue'; import {storeToRefs} from 'pinia'; const mainStore = useMainStore(); const {count2} = storeToRefs(mainStore); const {add2} = mainStore; console.log(mainStore) const number = ref(100); const resetStore = () => { mainStore.$reset(); } const addCount = () => { mainStore.add(); }; const updateCount = () => { mainStore.update(number); } onMounted(() => { mainStore.getList(); }) </script>
效果:
分別觸發(fā) add2 兩次,addCount、getList 一次后的效果
4.2 組合式寫(xiě)法
在組合式 API 中:
- ref() 相當(dāng)于 state 屬性;
- computed() 相當(dāng)于 getters;
- function() 相當(dāng)于 actions;
// store/count.js import { defineStore } from 'pinia'; import {computed, ref} from 'vue'; import axios from 'axios'; // 第一個(gè)參數(shù)是應(yīng)用中 Store 的唯一 ID export const useCountStore = defineStore('count',() => { // state const count = ref(0); const count2 = ref(0); const list = ref([]); // getter const doubleCount = computed(() => { return count.value*2 }) // 同步action const add = () => { count.value++; } const update = (val) =>{ count.value = val.value; } const add2 = () => { count2.value++; } // 異步action const getList = async () => { const res = await axios.get('https://api.oioweb.cn/api/common/history'); if(res.data.code == 200){ list.value = res.data.result || []; } } return{ count, count2, doubleCount, list, add, update, add2, getList, } })
在組件中使用
<template> <div class="count">state:{{countStore.count}}</div> <div class="count">getters:{{countStore.doubleCount}}</div> <div class="btnWrap"> <button @click="resetStore">重 置</button> <button @click="addCount">增 加</button> <button @click="updateCount">更新至100</button> </div> <hr/> <div class="count">state:{{count2}}</div> <div class="btnWrap"> <button @click="add2">增 加</button> </div> <hr/> <h3>歷史上的今天</h3> <ul class="list"> <li v-for="(item,index) in countStore.list" :key="index"> {{item.year}}年 - {{item.title}} </li> </ul> </template>
<script setup> import {useCountStore} from '@/store/count.js'; import {onMounted,ref} from 'vue'; import {storeToRefs} from 'pinia'; const countStore = useCountStore(); const {count2} = storeToRefs(countStore); const {add2} = countStore; console.log(countStore) const number = ref(100); const resetStore = () => { countStore.$reset(); } const addCount = () => { countStore.add(); }; const updateCount = () => { countStore.update(number); } onMounted(() => { countStore.getList(); }) </script>
效果:
分別觸發(fā) add2 兩次,addCount、getList 一次后的效果
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Vue3+Vite項(xiàng)目中引入pinia和pinia-plugin-persistedstate的方法代碼
- vue3配置permission.js和router、pinia實(shí)現(xiàn)路由攔截的簡(jiǎn)單步驟
- vue3?pinia實(shí)現(xiàn)持久化詳解
- vue3中pinia的使用方法
- vue3 pinia使用及持久化注冊(cè)
- vue3項(xiàng)目使用pinia狀態(tài)管理器的使用
- Vue狀態(tài)管理工具Pinia的安裝與使用教程
- vue3使用Pinia修改state的三種方法(直接修改,$patch,actions)
- Vue中Pinia的各種詳細(xì)說(shuō)明和使用示例
相關(guān)文章
vue的全局變量和全局?jǐn)r截請(qǐng)求器的示例代碼
這篇文章主要介紹了vue的全局變量和全局?jǐn)r截請(qǐng)求器的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09Vuex狀態(tài)機(jī)的快速了解與實(shí)例應(yīng)用
Vuex是專門(mén)為Vuejs應(yīng)用程序設(shè)計(jì)的狀態(tài)管理工具,這篇文章主要給大家介紹了關(guān)于Vuex狀態(tài)機(jī)快速了解與實(shí)例應(yīng)用的相關(guān)資料,需要的朋友可以參考下2021-06-06vue使用高德地圖點(diǎn)擊下鉆上浮效果的實(shí)現(xiàn)思路
這篇文章主要介紹了vue使用高德地圖點(diǎn)擊下鉆 上浮效果的實(shí)現(xiàn)思路,本文以浙江省為例通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2019-10-10vue根據(jù)進(jìn)入的路由進(jìn)行原路返回的方法
今天小編就為大家分享一篇vue根據(jù)進(jìn)入的路由進(jìn)行原路返回的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果
這篇文章主要為大家詳細(xì)介紹了vue+swiper實(shí)現(xiàn)側(cè)滑菜單效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Vue動(dòng)態(tài)樣式方法實(shí)例總結(jié)
在vue項(xiàng)目中,很多場(chǎng)景要求我們動(dòng)態(tài)改變?cè)氐臉邮?下面這篇文章主要給大家介紹了關(guān)于Vue動(dòng)態(tài)樣式方法的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02html+vue實(shí)現(xiàn)分頁(yè)功能的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何使用html+vue實(shí)現(xiàn)簡(jiǎn)單的分頁(yè)功能,文中的示例代碼簡(jiǎn)潔易懂,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04vant的Loading加載動(dòng)畫(huà)組件的使用(通過(guò)接口拿數(shù)據(jù)時(shí)顯示加載狀態(tài))
這篇文章主要介紹了vant的Loading加載動(dòng)畫(huà)組件的使用,通過(guò)接口拿數(shù)據(jù)時(shí)顯示加載狀態(tài),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01vue項(xiàng)目接口管理,所有接口都在apis文件夾中統(tǒng)一管理操作
這篇文章主要介紹了vue項(xiàng)目接口管理,所有接口都在apis文件夾中統(tǒng)一管理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08