您好,登錄后才能下訂單哦!
這篇文章主要介紹“Vue3狀態管理之Pinia怎么使用”,在日常操作中,相信很多人在Vue3狀態管理之Pinia怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Vue3狀態管理之Pinia怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Vue 3 將在 2022 年 2 月 7 日 成為新的默認版本
基于 Vite 的極速構建工具鏈
<script setup> 帶來的開發體驗更絲滑的組合式 API 語法
Volar 提供的單文件組件 TypeScript IDE 支持
vue-tsc 提供的針對單文件組件的命令行類型檢查和生成
Pinia 提供的更簡潔的狀態管理
新的開發者工具擴展,同時支持 Vue 2/Vue 3,并且提供一個插件系統來允許社區庫自行擴展開發者工具面板。
官方地址:https://pinia.vuejs.org/
Pinia 是 Vuex4 的升級版,也就是 Vuex5
Pinia 極大的簡化了Vuex的使用,是 Vue3的新的狀態管理工具
Pinia 對 ts的支持更好,性能更優, 體積更小,無 mutations,可用于 Vue2 和 Vue3
Pinia支持Vue Devtools、 模塊熱更新和服務端渲染
  Vuex 與 Pinia 對比
Vuex 中核心部分: State、Getters、Mutations(同步) 和 Actions(異步)
Pinia 中核心部分: State、Getters 和 Actions(同步異步均支持)
  Pinia 各部分作用
State: 類似于組件中data,用于存儲全局狀態
Getters: 類似于組件中的computed,根據已有的State封裝派生數據,也具有緩存的特性
Actions: 類似于組件中的methods,用于封裝業務邏輯,同步異步均可以
  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 }) }, }, })
① 創建一個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" },
③ 創建 pinia 實例并掛載到 vue中
// main.ts 文件 import { createApp } from 'vue' import App from './App.vue' import {createPinia} from 'pinia' // 創建 Pinia 實例 const pinia = createPinia() // 創建 Vue 實例 const app = createApp(App) // 掛載到 Vue 根實例 app.use(pinia) app.mount('#app')
④ 在src文件下創建一個store文件夾,并添加index.ts
// store/index.ts import { defineStore } from 'pinia' // 1. 定義容器、導出容器 // 參數1:容器的ID,必須是唯一的,后面Pinia會把所有的容器掛載到根容器 // 參數2:一些選項對象,也就是state、getter和action // 返回值:一個函數,調用即可得到容器實例 export const useMainStore = defineStore('main',{ // 類似于Vue2組件中的data,用于存儲全局狀態數據,但有兩個要求 // 1. 必須是函數,目的是為了在服務端渲染的時候避免交叉請求導致的數據狀態污染 // 2. 必須是箭頭函數,這樣是為了更好的 TS 類型推導 state:()=>{ return { info:"pinia 可以使用" } }, getters:{}, actions:{} }) // 2. 使用容器中的 state // 3. 通過 getter 修改 state // 4. 使用容器中的 action 同步和異步請求
⑤ 在組件中使用
<template> <h2>{{ mainStore.info}}</h2> </template> <script lang="ts" setup> import { useMainStore } from "../store"; const mainStore = useMainStore(); </script> <style> </style>
狀態管理中
// store/index.ts state:()=>{ return { info:"pinia 可以使用", count:10 } },
組件中
<template> <h2>{{ mainStore.count }}</h2> <h2>{{ mainStore.info }}</h2> <hr /> <h2>{{ count }}</h2> <h2>{{ info }}</h2> <p> <button @click="alertData">修改數據</button> </p> </template> <script lang="ts" setup> import { toRefs } from 'vue' import { storeToRefs } from 'pinia' import { useMainStore } from "../store"; const mainStore = useMainStore(); // 解構數據,但是得到的數據是不具有響應式的,只是一次性的 // 相當于僅僅只是...mainStore而已,只是做了reactive處理,并沒有做toRefs // const { count, info } = useMainStore(); // 解決方法: // 1. 通過使用toRefs函數,因為前面所說相當于是通過reactive處理,因此可以 // const { count, info } = toRefs(mainStore); // 2. 通過pinia中提供的storeToRefs方法來解決,推薦使用 const { count, info } = storeToRefs(mainStore); const alertData = () => { mainStore.count += 10 } </script> <style> </style>
一般的修改
const alertData = () => { // 方式一:最簡單的方法,如下 // 解構后更改方式 // count.value += 10 // 結構前更改方式 // mainStore.count += 10 // 方式二:若要同時修改多個數據,建議使用$patch來實現批量更新,在內部做了優化 // mainStore.$patch({ // count: mainStore.count + 1, // info: "hello" // }) // 方式三:更好的批量更新方法,通過$patch傳遞一個函數來實現,這里的state就是useMainStore容器中的state mainStore.$patch(state => { state.count += 10 state.info = "pinia批量更新" }) }
通過actions修改
// store/index.ts // 類似于vue2組件的methods,用于封裝業務邏輯,修改state // // 注意:不能使用箭頭函數來定義actions,因為箭頭函數綁定外部的this actions:{ changeState (){ this.count += 10 this.info = "actions修改數據" }, changeStates (num:number){ this.count += num + 2 this.info = "actions修改數據" } }
const alertData = () => { // 方式一:最簡單的方法,如下 // 解構后更改方式 // count.value += 10 // 結構前更改方式 // mainStore.count += 10 // 方式二:若要同時修改多個數據,建議使用$patch來實現批量更新,在內部做了優化 // mainStore.$patch({ // count: mainStore.count + 1, // info: "hello" // }) // 方式三:更好的批量更新方法,通過$patch傳遞一個函數來實現,這里的state就是useMainStore容器中的state // mainStore.$patch(state => { // state.count += 10 // state.info = "pinia批量更新" // }) // 方式四:通過 actions 來修改數據 mainStore.changeState() mainStore.changeStates(10) }
定義
// 類似于組件的computed,用來封裝計算屬性,具有緩存的功能 getters:{ // 函數接收一個可選參數:state狀態對象 count10(state){ return state.count += 10 }, count10(state){ return this.count += 10 }, // 若使用this.count,則必須指明返回數據的類型 count11():number{ return this.count += 11 } },
使用
<h2>{{ mainStore.count10 }}</h2>
保存至localStorage中
import { defineStore } from 'pinia'; const useLoginStore = defineStore({ id: 'login', // state: () => ({ // num: 1, // }), state: () => ({ info: 'pinia 可以使用', }), getters: {}, actions: { alertInfo() { this.info = '可以可以,這個秒'; }, }, }); // 數據持久化 // 1. 保存數據 const instance = useLoginStore(); instance.$subscribe((_, state) => { localStorage.setItem('login-store', JSON.stringify({ ...state })); }); // 2. 獲取保存的數據,先判斷有無,無則用先前的 const old = localStorage.getItem('login-store'); if (old) { instance.$state = JSON.parse(old); } export default useLoginStore;
使用 插件 pinia-plugin-persist 可以輔助實現數據持久化功能
# 安裝插件 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');
// 接著在對應的 store 里開啟 persist 即可。數據默認存在 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 可以使用', }), // 開啟數據緩存 persist: { enabled: true, }, getters: {}, actions: { alertInfo() { this.info = '可以可以,這個秒'; }, }, }); export default useLoginStore;
其它設置,自定義保存名稱,保存位置和需要保存的數據
// 開啟數據緩存 persist: { enabled: true, strategies: [ { // 自定義名稱 key: 'login_store', // 保存位置,默認保存在sessionStorage storage: localStorage, // 指定要持久化的數據,默認所有 state 都會進行緩存,你可以通過 paths 指定要持久化的字段,其他的則不會進行持久化。 paths: ['age'], }, ], },
到此,關于“Vue3狀態管理之Pinia怎么使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。