Vue3狀態(tài)管理之Pinia的入門使用教程
Vue3 新的發(fā)展方向(來源于尤大知乎)
Vue 3 將在 2022 年 2 月 7 日 成為新的默認版本
基于 Vite 的極速構(gòu)建工具鏈
<script setup> 帶來的開發(fā)體驗更絲滑的組合式 API 語法
Volar 提供的單文件組件 TypeScript IDE 支持
vue-tsc 提供的針對單文件組件的命令行類型檢查和生成
Pinia 提供的更簡潔的狀態(tài)管理
新的開發(fā)者工具擴展,同時支持 Vue 2/Vue 3,并且提供一個插件系統(tǒng)來允許社區(qū)庫自行擴展開發(fā)者工具面板。
一、Pinia 簡介與基礎(chǔ)
1.1 Pinia 簡介
- 官方地址:https://pinia.vuejs.org/
- Pinia 是 Vuex4 的升級版,也就是 Vuex5
- Pinia 極大的簡化了Vuex的使用,是 Vue3的新的狀態(tài)管理工具
- Pinia 對 ts的支持更好,性能更優(yōu), 體積更小,無 mutations,可用于 Vue2 和 Vue3
- Pinia支持Vue Devtools、 模塊熱更新和服務(wù)端渲染
1.2 Pinia 基礎(chǔ)
Vuex 與 Pinia 對比
- Vuex 中核心部分: State、Getters、Mutations(同步) 和 Actions(異步)
- Pinia 中核心部分: State、Getters 和 Actions(同步異步均支持)
Pinia 各部分作用
- State: 類似于組件中data,用于存儲全局狀態(tài)
- Getters: 類似于組件中的computed,根據(jù)已有的State封裝派生數(shù)據(jù),也具有緩存的特性
- Actions: 類似于組件中的methods,用于封裝業(yè)務(wù)邏輯,同步異步均可以
Pinia 官方示例JS版本
import { defineStore } from 'pinia'
export const todos = defineStore('todos', {
state: () => ({
/** @type {{ text: string, id: number, isFinished: boolean }[]} */
todos: [],
/** @type {'all' | 'finished' | 'unfinished'} */
filter: 'all',
// type will be automatically inferred to number
nextId: 0,
}),
getters: {
finishedTodos(state) {
// autocompletion! ?
return state.todos.filter((todo) => todo.isFinished)
},
unfinishedTodos(state) {
return state.todos.filter((todo) => !todo.isFinished)
},
/**
* @returns {{ text: string, id: number, isFinished: boolean }[]}
*/
filteredTodos(state) {
if (this.filter === 'finished') {
// call other getters with autocompletion ?
return this.finishedTodos
} else if (this.filter === 'unfinished') {
return this.unfinishedTodos
}
return this.todos
},
},
actions: {
// any amount of arguments, return a promise or not
addTodo(text) {
// you can directly mutate the stat 00e
this.todos.push({ text, id: this.nextId++, isFinished: false })
},
},
})
二、Pinia 在Vue3-Vite中的使用
2.1 基礎(chǔ)使用流程
① 創(chuàng)建一個vue vite項目
PS C:\Users\FORGET\Desktop\vue-pinia-demo> npm init vite@latest Need to install the following packages: create-vite@latest Ok to proceed? (y) y √ Project name: ... pinia-demo √ Select a framework: ? vue √ Select a variant: ? vue-ts Scaffolding project in C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo... Done. Now run: cd pinia-demo npm install npm run dev PS C:\Users\FORGET\Desktop\vue-pinia-demo> cd .\pinia-demo\ PS C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo> npm install
② 安裝 pinia,-S是為了將其保存至package.json中,便于Git管理給其他人的使用
PS C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo> npm install pinia -S
# package.json文件中
"dependencies": {
"pinia": "^2.0.9",
"vue": "^3.2.25"
},
③ 創(chuàng)建 pinia 實例并掛載到 vue中
// main.ts 文件
import { createApp } from 'vue'
import App from './App.vue'
import {createPinia} from 'pinia'
// 創(chuàng)建 Pinia 實例
const pinia = createPinia()
// 創(chuàng)建 Vue 實例
const app = createApp(App)
// 掛載到 Vue 根實例
app.use(pinia)
app.mount('#app')
④ 在src文件下創(chuàng)建一個store文件夾,并添加index.ts
// store/index.ts
import { defineStore } from 'pinia'
// 1. 定義容器、導(dǎo)出容器
// 參數(shù)1:容器的ID,必須是唯一的,后面Pinia會把所有的容器掛載到根容器
// 參數(shù)2:一些選項對象,也就是state、getter和action
// 返回值:一個函數(shù),調(diào)用即可得到容器實例
export const useMainStore = defineStore('main',{
// 類似于Vue2組件中的data,用于存儲全局狀態(tài)數(shù)據(jù),但有兩個要求
// 1. 必須是函數(shù),目的是為了在服務(wù)端渲染的時候避免交叉請求導(dǎo)致的數(shù)據(jù)狀態(tài)污染
// 2. 必須是箭頭函數(shù),這樣是為了更好的 TS 類型推導(dǎo)
state:()=>{
return {
info:"pinia 可以使用"
}
},
getters:{},
actions:{}
})
// 2. 使用容器中的 state
// 3. 通過 getter 修改 state
// 4. 使用容器中的 action 同步和異步請求
⑤ 在組件中使用
<template>
<h1>{{ mainStore.info}}</h1>
</template>
<script lang="ts" setup>
import { useMainStore } from "../store";
const mainStore = useMainStore();
</script>
<style>
</style>
2.2 state 中數(shù)據(jù)的解構(gòu)訪問
狀態(tài)管理中
// store/index.ts
state:()=>{
return {
info:"pinia 可以使用",
count:10
}
},
組件中
<template>
<h1>{{ mainStore.count }}</h1>
<h1>{{ mainStore.info }}</h1>
<hr />
<h1>{{ count }}</h1>
<h1>{{ info }}</h1>
<p>
<button @click="alertData">修改數(shù)據(jù)</button>
</p>
</template>
<script lang="ts" setup>
import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from "../store";
const mainStore = useMainStore();
// 解構(gòu)數(shù)據(jù),但是得到的數(shù)據(jù)是不具有響應(yīng)式的,只是一次性的
// 相當于僅僅只是...mainStore而已,只是做了reactive處理,并沒有做toRefs
// const { count, info } = useMainStore();
// 解決方法:
// 1. 通過使用toRefs函數(shù),因為前面所說相當于是通過reactive處理,因此可以
// const { count, info } = toRefs(mainStore);
// 2. 通過pinia中提供的storeToRefs方法來解決,推薦使用
const { count, info } = storeToRefs(mainStore);
const alertData = () => {
mainStore.count += 10
}
</script>
<style>
</style>
2.3 state 中數(shù)據(jù)的修改方式(actions和組件中)
一般的修改
const alertData = () => {
// 方式一:最簡單的方法,如下
// 解構(gòu)后更改方式
// count.value += 10
// 結(jié)構(gòu)前更改方式
// mainStore.count += 10
// 方式二:若要同時修改多個數(shù)據(jù),建議使用$patch來實現(xiàn)批量更新,在內(nèi)部做了優(yōu)化
// mainStore.$patch({
// count: mainStore.count + 1,
// info: "hello"
// })
// 方式三:更好的批量更新方法,通過$patch傳遞一個函數(shù)來實現(xiàn),這里的state就是useMainStore容器中的state
mainStore.$patch(state => {
state.count += 10
state.info = "pinia批量更新"
})
}
通過actions修改
// store/index.ts
// 類似于vue2組件的methods,用于封裝業(yè)務(wù)邏輯,修改state
// // 注意:不能使用箭頭函數(shù)來定義actions,因為箭頭函數(shù)綁定外部的this
actions:{
changeState (){
this.count += 10
this.info = "actions修改數(shù)據(jù)"
},
changeStates (num:number){
this.count += num + 2
this.info = "actions修改數(shù)據(jù)"
}
}
const alertData = () => {
// 方式一:最簡單的方法,如下
// 解構(gòu)后更改方式
// count.value += 10
// 結(jié)構(gòu)前更改方式
// mainStore.count += 10
// 方式二:若要同時修改多個數(shù)據(jù),建議使用$patch來實現(xiàn)批量更新,在內(nèi)部做了優(yōu)化
// mainStore.$patch({
// count: mainStore.count + 1,
// info: "hello"
// })
// 方式三:更好的批量更新方法,通過$patch傳遞一個函數(shù)來實現(xiàn),這里的state就是useMainStore容器中的state
// mainStore.$patch(state => {
// state.count += 10
// state.info = "pinia批量更新"
// })
// 方式四:通過 actions 來修改數(shù)據(jù)
mainStore.changeState()
mainStore.changeStates(10)
}
2.4 getters 的使用
定義
// 類似于組件的computed,用來封裝計算屬性,具有緩存的功能
getters:{
// 函數(shù)接收一個可選參數(shù):state狀態(tài)對象
count10(state){
return state.count += 10
},
count10(state){
return this.count += 10
},
// 若使用this.count,則必須指明返回數(shù)據(jù)的類型
count11():number{
return this.count += 11
}
},
使用
<h1>{{ mainStore.count10 }}</h1>
三、Pinia 數(shù)據(jù)持久化
保存至localStorage中
import { defineStore } from 'pinia';
const useLoginStore = defineStore({
id: 'login',
// state: () => ({
// num: 1,
// }),
state: () => ({
info: 'pinia 可以使用',
}),
getters: {},
actions: {
alertInfo() {
this.info = '可以可以,這個秒';
},
},
});
// 數(shù)據(jù)持久化
// 1. 保存數(shù)據(jù)
const instance = useLoginStore();
instance.$subscribe((_, state) => {
localStorage.setItem('login-store', JSON.stringify({ ...state }));
});
// 2. 獲取保存的數(shù)據(jù),先判斷有無,無則用先前的
const old = localStorage.getItem('login-store');
if (old) {
instance.$state = JSON.parse(old);
}
export default useLoginStore;
使用 插件 pinia-plugin-persist 可以輔助實現(xiàn)數(shù)據(jù)持久化功能
# 安裝插件 pnpm install pinia-plugin-persist --save
// main.ts文件中
import { createPinia } from 'pinia';
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import piniaPluginPersist from 'pinia-plugin-persist';
const pinia = createPinia();
pinia.use(piniaPluginPersist);
const app = createApp(App);
app.use(router);
app.use(pinia);
app.mount('#app');
// 接著在對應(yīng)的 store 里開啟 persist 即可。數(shù)據(jù)默認存在 sessionStorage 里,并且會以 store 的 id 作為 key。
import { defineStore } from 'pinia';
import piniaPluginPersist from 'pinia-plugin-persist';
const useLoginStore = defineStore({
id: 'login',
// state: () => ({
// num: 1,
// }),
state: () => ({
info: 'pinia 可以使用',
}),
// 開啟數(shù)據(jù)緩存
persist: {
enabled: true,
},
getters: {},
actions: {
alertInfo() {
this.info = '可以可以,這個秒';
},
},
});
export default useLoginStore;
其它設(shè)置,自定義保存名稱,保存位置和需要保存的數(shù)據(jù)
// 開啟數(shù)據(jù)緩存
persist: {
enabled: true,
strategies: [
{
// 自定義名稱
key: 'login_store',
// 保存位置,默認保存在sessionStorage
storage: localStorage,
// 指定要持久化的數(shù)據(jù),默認所有 state 都會進行緩存,你可以通過 paths 指定要持久化的字段,其他的則不會進行持久化。
paths: ['age'],
},
],
},
總結(jié)
到此這篇關(guān)于Vue3狀態(tài)管理之Pinia入門使用的文章就介紹到這了,更多相關(guān)Vue3狀態(tài)管理Pinia使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Vue3之狀態(tài)管理器(Pinia)詳解及使用方式
- Vue3中的pinia使用方法總結(jié)(建議收藏版)
- vue3項目使用pinia狀態(tài)管理器的使用
- vue3項目引入pinia報錯的簡單解決
- vue3 pinia踩坑及解決方案詳解
- Vue3中pinia的使用與持久化處理詳解
- Vue3組件不發(fā)生變化如何監(jiān)聽pinia中數(shù)據(jù)變化
- vue3中vuex與pinia的踩坑筆記記錄
- vue3搭配pinia的踩坑實戰(zhàn)記錄
- vue3?pinia實現(xiàn)持久化詳解
- vue3中使用pinia(大菠蘿)狀態(tài)管理倉庫的項目實踐
- Vue3 狀態(tài)管理 Pinia 入門指南
相關(guān)文章
Vue3之路由的query參數(shù)和params參數(shù)用法
這篇文章主要介紹了Vue3之路由的query參數(shù)和params參數(shù)用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03
vue實現(xiàn)導(dǎo)入json解析成動態(tài)el-table樹表格
本文主要介紹了vue實現(xiàn)導(dǎo)入json解析成動態(tài)el-table樹表格,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
解決ant design vue中樹形控件defaultExpandAll設(shè)置無效的問題
這篇文章主要介紹了解決ant design vue中樹形控件defaultExpandAll設(shè)置無效的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
ant-design-vue table分頁onShowSizeChange后的pageNo解決
這篇文章主要介紹了ant-design-vue table分頁onShowSizeChange后的pageNo的問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
vue-cli5.0?webpack?采用?copy-webpack-plugin?打包復(fù)制文件的方法
今天就好好說說vue-cli5.0種使用copy-webpack-plugin插件該如何配置的問題。這里我們安裝的 copy-webpack-plugin 的版本是 ^11.0.0,感興趣的朋友一起看看吧2022-06-06
詳解vue2父組件傳遞props異步數(shù)據(jù)到子組件的問題
本篇文章主要介紹了vue2父組件傳遞props異步數(shù)據(jù)到子組件的問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06

