帶你熟練掌握Vue3之Pinia狀態(tài)管理
一、概念
1. Pinia => Pinia
Pinia(發(fā)音為/pi?nj?/,如英語中的“peenya”)是最接近piña(西班牙語中的菠蘿)的詞
- Pinia開始于大概2019年,最初是作為一個實驗為Vue重新設(shè)計狀態(tài)管理,讓它用起來像組合式API(Composition API)
- 從那時到現(xiàn)在,最初的設(shè)計原則依然是相同的,并且目前同時兼容Vue2、Vue3,也并不要求你使用Composition API
- Pinia本質(zhì)上依然是一個狀態(tài)管理的庫,用于跨組件、頁面進行狀態(tài)共享(這點和Vuex、Redux一樣)
2. Pinia和Vuex的對比
01 - 不是已經(jīng)有Vuex了嗎?為什么還要用Pinia
- Pinia 最初是為了探索 Vuex 的下一次迭代會是什么樣子,結(jié)合了 Vuex 5 核心團隊討論中的許多想法
- 最終,團隊意識到Pinia已經(jīng)實現(xiàn)了Vuex5中大部分內(nèi)容,所以最終決定用Pinia來替代Vuex
- 與 Vuex 相比,Pinia 提供了一個更簡單的 API,具有更少的儀式,提供了 Composition-API 風(fēng)格的 API
- 最重要的是,在與 TypeScript 一起使用時具有可靠的類型推斷支持
02 - 和Vuex相比,Pinia有很多的優(yōu)勢
- mutations 不再存在
- 他們經(jīng)常被認為是 非常 冗長
- 他們最初帶來了 devtools 集成,但這不再是問題
- 更友好的TypeScript支持,Vuex之前對TS的支持很不友好
- 不再有modules的嵌套結(jié)構(gòu)
- 可以靈活使用每一個store,它們是通過扁平化的方式來相互使用的
- 也不再有命名空間的概念,不需要記住它們的復(fù)雜關(guān)系
- Pinia的store中的 getters、actions 可以使用this,this代表當前sotre對象
二、使用Pinia
1. 安裝
npm install pinia
2. 創(chuàng)建Pinia
創(chuàng)建stores文件夾,并在其中創(chuàng)建個index.js
// 1. 導(dǎo)入 import { createPinia } from 'pinia'; // 2. 創(chuàng)建 const pinia = createPinia(); // 3. 導(dǎo)出 export default pinia;
3. 在main.js中引入
import { createApp } from 'vue'; import App from './App.vue'; // 1. 導(dǎo)入 import pinia from './stores'; // 2. use一下 createApp(App).use(pinia).mount('#app');
三、Store
1. 概念
Store :
- 一個 Store (如 Pinia)是一個實體,它會持有為綁定到你組件樹的狀態(tài)和業(yè)務(wù)邏輯,也就是保存了全局的狀態(tài)
- 它有點像始終存在,并且每個人都可以讀取和寫入的組件
- 你可以在你的應(yīng)用程序中定義任意數(shù)量的Store來管理你的狀態(tài)
Store有三個核心概念 :
- state、getters、actions
- 等同于組件的data、computed、methods
- 一旦 store 被實例化,可以直接在 store 上面訪問 state、getters 和 actions 中定義的任何屬性
2. 創(chuàng)建
定義一個Store :
- Store 是使用 defineStore() 定義
- 并且它需要一個唯一名稱,作為第一個參數(shù)傳遞
在stores文件夾創(chuàng)建 counter.js 文件
// 1, 導(dǎo)入 import { defineStore } from 'pinia'; // 2. 創(chuàng)建一個store /** * 第一個參數(shù) : 唯一的名稱 * 第二個參數(shù) : 傳入配置 * 返回值 : 返回一個函數(shù),調(diào)用這個函數(shù),即可拿到當前store */ const userCounterStore = defineStore('counterStore', { state: () => ({ count: 66 }) }); export default userCounterStore;
3. 使用
<template> <div class="app">App 頁面</div> <h2>1. counterStore : {{ counterStore.count }}</h2> <h2>2. toRefs : {{ aCount }}</h2> <h2>3. storeToRefs : {{ bCount }}</h2> <button @click="changCount">改變count</button> </template> <script setup> import { toRefs } from 'vue'; import { storeToRefs } from 'pinia'; // 1. 導(dǎo)入該函數(shù) import userCounterStore from '@/stores/module/counter'; // 2. 調(diào)用,獲得store const counterStore = userCounterStore(); // 3. 拿到state值 /** * 注意 : 直接解構(gòu)可以拿到值,但并不是響應(yīng)式的了 * 1. 使用 toRefs * 2. 使用pinia提供的 storeToRefs */ // toRefs const { count: aCount } = toRefs(counterStore); // storeToRefs const { count: bCount } = storeToRefs(counterStore); // 監(jiān)聽點擊 const changCount = () => { // 可以直接操作?。?! counterStore.count++; }; </script>
4. 效果
四、核心概念State
1. 定義State
// 1, 導(dǎo)入 import { defineStore } from 'pinia'; // 2. 創(chuàng)建一個store /** * 第一個參數(shù) : 唯一的名稱 * 第二個參數(shù) : 傳入配置 * 返回值 : 返回一個函數(shù),調(diào)用這個函數(shù),即可拿到當前store */ const userCounterStore = defineStore('counterStore', { state: () => ({ count: 66, name: 'coder', age: 19 }) }); export default userCounterStore;
2. 讀取寫入State
默認情況下,可以通過 store 實例訪問狀態(tài)來直接讀取和寫入狀態(tài)
<script setup> import Home from './views/Home.vue'; // 1. 導(dǎo)入該函數(shù) import { toRefs } from 'vue'; import { storeToRefs } from 'pinia'; import userCounterStore from '@/stores/module/counter'; // 2. 調(diào)用,獲得store const counterStore = userCounterStore(); // 3. 拿到state值 const { count } = storeToRefs(counterStore); // 監(jiān)聽點擊 const changCount = () => { // 1. 讀取 console.log(counterStore.count); // 2. 寫入 counterStore.count++; }; </script>
3. 重置State
可以通過調(diào)用 store 上的 $reset() 方法將狀態(tài) 重置 到其初始值
// 重置 const resetState = () => { // 回到初始值 counterStore.$reset(); };
4. 改變State
除了直接用 store.counter++ 修改 store,還可以調(diào)用 $patch 方法
允許同時應(yīng)用多個更改
// 監(jiān)聽點擊 const changCount = () => { // 一起更改數(shù)據(jù) counterStore.$patch({ count: 99, name: 'star', // 如果輸入新增的屬性,沒有用噠! buy: ref('abvc') }); console.log(counterStore); };
5. 替換State
可以通過將其 $state 屬性設(shè)置為新對象來替換 Store 的整個狀態(tài)
五、核心概念Getters
1. 基本使用
代碼
const userCounterStore = defineStore('counterStore', { state: () => ({ count: 66, name: 'coder', age: 19 }), getters: { // 1. 定義getterts doubleCount(state) { // 2. 通過state參數(shù)拿到count console.log(state.count); // 3. 通過this拿到參數(shù) console.log(this.count); } } });
使用
<template> <div>home</div> <h2>count : {{ counterStore.count }}</h2> <hr /> <h2>count : {{ counterStore.doubleCount }}</h2> <button @click="changCount">改變count</button> </template> <script setup> import { toRefs } from 'vue'; import userCounterStore from '@/stores/module/counter'; // 1. 獲取store const counterStore = userCounterStore(); // 2. 解構(gòu),變成響應(yīng)式 const { doubleCount } = toRefs(counterStore); console.log(doubleCount); // 監(jiān)聽點擊 const changCount = () => { // 3. 改變store counterStore.count++; // 4. 輸出 console.log(doubleCount.value); }; </script>
2. 在getter中使用其他的getter
getters: { doubleCount(state) { return this.count * 2; }, othersGetter() { // 通過this來拿 return this.doubleCount; } }
3. getters支持返回一個函數(shù)
可以用來傳遞參數(shù)到getters
代碼
getters: { doubleCount(state) { return this.count * 2; }, formatName() { // 返回一個函數(shù),可以傳遞參數(shù)進來 return (lastName) => { return this.name + lastName; }; } }
使用
<template> <h2>{{ counterStore.formatName('123') }}</h2> <button @click="changCount">改變count</button> </template> <script setup> import { toRefs } from 'vue'; import userCounterStore from '@/stores/module/counter'; // 1. 獲取store const counterStore = userCounterStore(); // 2. 解構(gòu),變成響應(yīng)式 const { formatName } = toRefs(counterStore); const changCount = () => { // 3. 使用函數(shù) console.log(formatName.value('444')); // 也可以直接使用,看情況而定 counterStore.formatName('123') }; </script>
4. getters使用別的store中的數(shù)據(jù)
導(dǎo)入其他的store,使用即可,很方便
userOtherStore(){ // 1. 導(dǎo)入其他soter const otherStore = userOtherStore() // 2. 拿到數(shù)據(jù) .... otherStore.getters() }
六、核心概念A(yù)ctions
actions => 非常適合定義業(yè)務(wù)邏輯
1. 基本使用
代碼
const userCounterStore = defineStore('counterStore', { state: () => ({ count: 66, name: 'coder', age: 19 }), actions: { increment() { this.count++; }, // 這里的參數(shù)指調(diào)用時傳遞過來的參數(shù) incrementNum(num) { this.count += num; } } });
使用
<script setup> import userCounterStore from '@/stores/module/counter'; // 1. 獲取store const counterStore = userCounterStore(); // 2. 解構(gòu) const { increment, incrementNum } = counterStore; // 3. 調(diào)用 increment(); incrementNum(33); </script>
2. 異步操作
代碼
const userCounterStore = defineStore('counterStore', { state: () => ({ arrList: [] }), actions: { async fetchDataList() { // 1. 請求 const res = await fetch('http:xxxxx'); const data = await res.json(); this.arrList = data.list; // 2. 返回值,相當于 return Promise.resolve(data) return data; } } });
使用
<script setup> import userCounterStore from '@/stores/module/counter'; // 1. 獲取store const counterStore = userCounterStore(); // 2. 解構(gòu) const { fetchDataList } = counterStore; // 3. 調(diào)用 fetchDataList().then((res) => { // 因為返回的時promise,所以可以在then中拿到數(shù)據(jù) console.log(res); }); </script>
總結(jié)
到此這篇關(guān)于Vue3之Pinia狀態(tài)管理的文章就介紹到這了,更多相關(guān)Vue3 Pinia狀態(tài)管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue.js 表格分頁ajax 異步加載數(shù)據(jù)
Vue.js通過簡潔的API提供高效的數(shù)據(jù)綁定和靈活的組件系統(tǒng).這篇文章主要介紹了vue.js 表格分頁ajax 異步加載數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2016-10-10laravel5.4+vue+element簡單搭建的示例代碼
本篇文章主要介紹了laravel5.4+vue+element簡單搭建的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08Vue數(shù)據(jù)變了但頁面沒有變的幾種情況及解決方法
如果,你發(fā)現(xiàn)自己需要在Vue中做一次強制更新,99.99%的情況,是你在某個地方做錯了事,本文給大家就介紹了Vue數(shù)據(jù)變了,但頁面沒有變的幾種情況及解決方法,并通過代碼示例介紹的非常詳細,需要的朋友可以參考下2024-08-08利用vue + element實現(xiàn)表格分頁和前端搜索的方法
眾所周知Element 是一套 Vue.js 后臺組件庫,它能夠幫助你更輕松更快速地開發(fā)后臺項目。下面這篇文章主要給大家介紹了關(guān)于利用vue + element實現(xiàn)表格分頁和前端搜索的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。2017-12-12