vue3探索——pinia高階使用

来源:https://www.cnblogs.com/cry0-0/archive/2023/09/16/17707386.html
-Advertisement-
Play Games

以下是一些 Pinia 的其他高階功能: storeToRefs():響應式解構倉庫,保證解構出來的數據是響應式的數據。 狀態持久化:Pinia 並沒有內置的狀態持久化功能,但你可以使用第三方庫或自定義插件來實現狀態的持久化。例如,你可以使用 localStorage 或 sessionStorag ...


以下是一些 Pinia 的其他高階功能:

  1. storeToRefs():響應式解構倉庫,保證解構出來的數據是響應式的數據。
  2. 狀態持久化:Pinia 並沒有內置的狀態持久化功能,但你可以使用第三方庫或自定義插件來實現狀態的持久化。例如,你可以使用 localStorage 或 sessionStorage 來將狀態保存在客戶端。
  3. 插件系統:Pinia 允許你編寫自定義插件,以擴展和定製狀態管理功能。你可以創建插件來處理持久化、日誌記錄、錯誤處理等任務,以適應你的特定需求。

響應式解構storeToRefs()

背景

在組件中訪問倉庫state,getters,actions時,總要在變數名前面帶上倉庫實例名,像下麵這樣,每個變數都這麼寫就會顯得很代碼很累贅。而直接解構的話,數據會丟失響應式。

import store from '@/store/senior.ts';
const userStore = store();
// 訪問state中的money,需要敲上'userStore.'
console.log(userStore.money);

// 直接解構,會丟失響應式
const { age } = userStore;

使用

在組件中使用storeToRefs可以保證解構出來的數據是響應式的數據。

import { storeToRefs } from 'pinia';
// ......
const { age } = storeToRefs(userStore);
console.log(age.value); // 別忘了 .value 這個小尾巴~

狀態持久化插件pinia-plugin-persist

pinia本身不提供持久化存儲狀態,這裡我們使用插件pinia-plugin-persist 進行持久化存儲。

npm: pinia-plugin-persist

Pinia Plugin Persist

1-安裝

  • yarn
yarn add pinia-plugin-persist
  • npm
npm install pinia-plugin-persist
  • pnpm
pnpm add pinia-plugin-persist

2-配置

src/store/index.ts中進行pinia的配置

import { createPinia } from 'pinia';
// 1-引入包
import piniaPersist from 'pinia-plugin-persist';

const pinia = createPinia();
// 2-使用pinia-plugin-persist插件
pinia.use(piniaPersist);

export default pinia;

src/main.ts

// ......
import { createApp } from 'vue';
import App from './App.vue';
// 1-引入pinia配置文件
import pinia from '@/store/index.ts';

const app = createApp(App);
// 2-使用pinia配置文件
app.use(pinia);

app.mount('#app');

打開項目下的ts配置文件tsconfig.json

{
  "compilerOptions": {
    "types": [
      "pinia-plugin-persist"
    ]
  },
}

3-使用

組合式API寫法

在倉庫中的defineStore() 第三個參數進行配置。

src/store/senior.ts

export const store = defineStore(
    'senior',
    () => {
        const age = ref(18);
        const money = ref(100);

        return {
            age,
            money
        }
    },
    {
        persist: {
            enabled: true, // 啟用持久化存儲
            // 存儲策略,可以配置多個存儲策略,一條策略對應一個存儲
            strategies: [
                {
                    key: 'local_age', // 存儲的key名
                    storage: localStorage, // 存儲方式
                    paths: ['money'] // 指定state欄位進行存儲
                },
                {
                    key: 'session_age',
                    storage: sessionStorage
                }
            ]
        }
    }
);

persist參數說明:

  • enabled:(true) 開啟持久化存儲。
  • strategies:(Array) 配置存儲策略,一條策略對應一個存儲。
    • key:(String) 存儲的key名。
    • storage:(Storage) 存儲方式,預設值是sessionStorage,可以是localStorage,也可以自定義存儲方式。
    • paths:(Array<string>) 指定某些state欄位進行存儲。若不配置,預設對整個state進行存儲。

選項式API寫法

src/store/senior.ts

export const store = defineStore('senior', {
    state() {
        return {
            age: 18,
            money: 100,
        }
    },
    persist: {
        enabled: true,
        strategies: [
            {
                key: 'local_age',
                storage: localStorage,
                paths: ['money']
            },
            {
                key: 'session_age',
                storage: sessionStorage
            }
        ]
    }
})

4-自定義存儲方式(cookie)

以下示例是對官方示例,進行優化的版本。

  • yarn
yarn add js-cookie
  • npm
npm install js-cookie
  • pnpm
pnpm add js-cookie

(2)定義倉庫

src/store/senior.ts

import { defineStore } from "pinia";
import { ref } from 'vue';
import Cookies from 'js-cookie';

// 1-定義存儲方式cookiesStorage
const cookiesStorage: Storage = {
    setItem(key, state) {
        // 判斷是值,還是整個倉庫
        const isKey = Object.keys(JSON.parse(state)).includes(key);
        if (isKey) {
            // 值
            return Cookies.set(key, JSON.stringify(JSON.parse(state)[key]), { expires: 3 });
        }
        else {
            // 倉庫state
            return Cookies.set(key, state, { expires: 3 });
        }

    },
    getItem(key) {
        // 判斷鍵值是否存在
        let value = Cookies.get(key);

        // 這裡應該需要判斷是整個倉庫state、還是值
        // 但目前沒有發現較好的判斷方法,所以persist必須配置paths
        /*
            // 如果是整個倉庫state
            return value;
        */

        return value ?
            // 存在,返回對應的值(parse處理,保證和原類型一致)
            JSON.stringify({ [key]: JSON.parse(value) })
            :
            // 不存在,不做parse處理,防undefined報錯
            JSON.stringify({ [key]: value });
    }
}

export const store = defineStore('senior', () => {
    const age = ref(123456);

    return {
        age,
    }
}, {
    persist: {
        enabled: true,
        strategies: [
            {
                storage: cookiesStorage, // 2-使用cookiesStorage存儲方式
                key: 'age',
                paths: ['age'] // 3-必須配置paths指定state欄位,否則數據會錯亂
            },
        ]
    }
});

!!!註意:目前,根據官方文檔的示例以及筆者的實踐,使用cookie進行持久化存儲,persist.strategies必須要配置paths 屬性,即無法預設存儲整個state,否則數據會出現錯亂(文章中就不演示了,有興趣的小伙伴兒可自行嘗試)。

插件系統

介紹

Pinia 插件是一個函數,函數接收一個參數context(上下文對象),可以獲取pinia實例、app應用等。

export functionmyPiniaPlugin(context) {
  context.pinia // 使用 `createPinia()` 創建的 pinia
  context.app // 使用 `createApp()` 創建的當前應用程式(僅限 Vue 3)
  context.store // 插件正在擴充的 store
  context.options // 定義存儲的選項對象傳遞給`defineStore()`
	// ...
};

然後使用 pinia.use() 將此函數傳遞給 pinia

pinia.use(myPiniaPlugin);

插件僅適用於在 將pinia傳遞給應用程式後創建的 store,否則將不會被應用。

功能

pinia官網描述pinia插件的功能:

  • 向 Store 添加新屬性
  • 定義 Store 時添加新選項
  • 為 Store 添加新方法
  • 包裝現有方法
  • 更改甚至取消操作
  • 實現本地存儲等副作用
  • 適用於特定 Store
  • ……

向 Store 添加新屬性

自定義插件函數返回(return)一個對象,對象中就是需要增加的屬性。

src/store/index.ts中,配置pinia插件。

import { createPinia } from 'pinia';
import { ref } from 'vue';
const pinia = createPinia();

// 1-定義插件:向store增加屬性
const expandStore = () => {
    // 2-這裡把需要增加的屬性return出去即可
    return {
        hello: ref(123) // 在所有store上添加'hello'狀態
    };
}
// 3-使用插件
pinia.use(expandStore);

export default pinia;

讀取 Store 配置項

可以通過插件函數context.options 來獲取每個store的額外配置,以便根據每個倉庫的功能進行區別開發。

1-定義 Store 時添加新選項

  • 在組合式API中,defineStore() 的第三個參數就是倉庫的配置項。
  • 在選項式API中,直接在defineStore() 的第二個參數(一個對象)中添加屬性作為配置項。

src/store/senior.ts

組合式API

import { defineStore } from "pinia";
export const store = defineStore('senior',
    () => {
        return {}
    },
    {
        haha: {
            option1: '123'
        }
    }
);

選項式API

import { defineStore } from "pinia";
export const store = defineStore('senior',
    {
        state: () => ({}),
        getters: {},
        actions: {},
        haha: {
            option1: '123'
        }
    }
);

2-插件中獲取每個store的選項

src/store/index.ts

// 這裡使用解構賦值,把options從context中解構出來
const expandStore = ({ options }) => {
    console.log('options', options);
}
pinia.use(expandStore);

監聽倉庫變化$subscribe()$onAction()

在插件中使用 store.$subscribe()和 store.$onAction(),可以監聽倉庫的變化。

pinia.use(({ store }) => {
  store.$subscribe(() => {
    // 在存儲變化的時候執行
  })
  store.$onAction(() => {
    // 在 action 的時候執行
  })
})

包裝或重寫現有方法

重寫$reset方法

可以參考上一篇博文,重寫了$reset方法:vue3探索——5分鐘快速上手大菠蘿pinia

import { createPinia } from 'pinia';
const pinia = createPinia();
 
// 1-使用pinia自定義插件
pinia.use(({ store }) => {
    // 2-獲取最開始的State
    const initialState = JSON.parse(JSON.stringify(store.$state));
    // 3-重寫$reset()方法
    store.$reset = () => {
        // 4-利用$patch()批量變更state,達到重置state的目的
        store.$patch(initialState);
    }
});
 
export default pinia;

暫時沒有更多辣~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 插件式架構,一種全新的、開放性的、高擴展性的架構體系。插件式架構設計好處很多,把擴展功能從框架中剝離出來,降低了框架的複雜度,讓框架更容易實現。擴展功能與框架以一種很松的方式耦合,兩者在保持介面不變的情況下,可以獨立變化和發佈。基於插件設計並不神秘,相反它比起一團泥的設計更簡單,更容易理解。 ...
  • 以下內容均來自Gitee的開源倉庫,具體的使用請移步Gitee:https://gitee.com/pojianbing/lazy-captcha 以下是我自己使用的具體方式 首先安裝NuGet包: Microsoft.Extensions.Caching.StackExchangeRedis La ...
  • 本文討論了零拷貝在優化數據傳輸效率方面的局限性。儘管零拷貝技術在減少數據傳輸過程中的記憶體拷貝次數方面有很大的優勢,但它並非適用於所有情況。文章介紹了一些其他的優化方法,如非同步I/O和直接I/O的組合、根據文件大小選擇不同的優化方式。至此,我們的電腦基礎專欄就結束了,不知道大家有沒有發現,操作系統底... ...
  • 1.列定義 說明:在MySQL中,列定義(Column Definition)是用於定義資料庫表中每一列的結構的語句。它指定了列的名稱、數據類型、長度、約束以及其他屬性。 2.主鍵和自增 主鍵:PRIMARY KEY是資料庫表中的一個欄位,被用作主鍵。主鍵用於唯一標識表中的每一行/記錄。在創建表時, ...
  • 在MySQL資料庫中,增刪改查操作是指對數據進行添加、刪除、查詢和修改的操作。這些操作在資料庫管理和維護中非常重要,可以幫助資料庫管理員和開發人員有效地管理數據和實現各種複雜的數據處理需求。 添加數據(增加操作):在MySQL中,添加數據通常使用INSERT語句。通過INSERT語句,開發人員可以將 ...
  • 數據類型的介紹: 數據類型(data_type)是指系統中所允許的數據的類型。資料庫中的每個列都應有適當的數據類型,用於限制或允許該列中存儲的數據。例如,列中存儲的為數字,則相應的數據類型應該為數值類型。 如果使用錯誤的數據類型可能會嚴重影響應用程式的功能和性能,所以在設計表時,應該特別重視數據列所 ...
  • 上文說到,資料庫的安裝和連接,接下來將給大家講解MySQL資料庫的基本語法及數據的類型 1.基本語法 (1).查看當前所有資料庫 : show databases; (2).創建資料庫 create database 資料庫名; 例如: create database gzy; (3).如果不確定數 ...
  • 1.MySQL是什麼? MySQL是一個關係型資料庫管理系統,由瑞典MySQL AB 公司開發,屬於 Oracle 旗下產品。它是最流行的關係型資料庫管理系統之一,在 WEB 應用方面,MySQL是最好的 RDBMS (Relational Database Management System,關係 ...
一周排行
    -Advertisement-
    Play Games
  • WPF本身不支持直接的3D繪圖,但是它提供了一些用於實現3D效果的高級技術。 如果你想要在WPF中進行3D繪圖,你可以使用兩種主要的方法: WPF 3D:這是一種在WPF應用程式中創建3D圖形的方式。WPF 3D提供了一些基本的3D形狀(如立方體、球體和錐體)以及一些用於控制3D場景和對象的工具(如 ...
  • 一、XML概述 XML(可擴展標記語言)是一種用於描述數據的標記語言,旨在提供一種通用的方式來傳輸和存儲數據,特別是Web應用程式中經常使用的數據。XML並不預定義標記。因此,XML更加靈活,並且可以適用於廣泛的應用領域。 XML文檔由元素(element)、屬性(attribute)和內容(con ...
  • 從今年(2023)三月份開始,Github開始強制用戶開啟兩步驗證2FA(雙因數)登錄驗證,毫無疑問,是出於安全層面的考慮,畢竟Github賬號一旦被盜,所有代碼倉庫都會毀於一旦,關於雙因數登錄的必要性請參見:別讓你的伺服器(vps)淪為肉雞(ssh暴力破解),密鑰驗證、雙向因數登錄值得擁有。 雙因 ...
  • 第一題 下列代碼輸入什麼? public class Test { public static Test t1 = new Test(); { System.out.println("blockA"); } static { System.out.println("blockB"); } publi ...
  • 本文主要涉及的問題:用ElementTree和XPath讀寫XML文件;解決ElementTree新增元素後再寫入格式不統一的問題;QTableWidget單元格設置控制項 ...
  • QStandardItemModel 類作為標準模型,主打“類型通用”,前一篇水文中,老周還沒提到樹形結構的列表,本篇咱們就好好探討一下這貨。 還是老辦法,咱們先做示例,然後再聊知識點。下麵這個例子,使用 QTreeView 組件來顯示數據,使用的列表模型比較簡單,只有一列。 #include <Q ...
  • 一、直充內充(充值方式) 直充: 包裝套餐直接充值到上游API系統。【PID/Smart】 (如:支付寶、微信 話費/流量/語音/簡訊 等 充值系統)。 內充(套餐打包常見物聯卡系統功能): 套餐包裝 適用於不同類型套餐 如 流量、簡訊、語音 等。 (目前已完善流量邏輯) 二、套餐與計費產品 計費產 ...
  • 在前面幾天中,我們學習了Dart基礎語法、可迭代集合,它們是Flutter應用研發的基本功。今天,我們繼續學習Flutter應用另一個必須掌握知識點:非同步編程(即Future和async/await)。它類似於Java中的FutureTask、JavaScript中的Promise。它是後續Flut... ...
  • 針對改動範圍大、影響面廣的需求,我通常會問上線了最壞情況是什麼?應急預案是什麼?你帶開關了嗎?。當然開關也是有成本的,接下來本篇跟大家一起交流下高頻發佈支撐下的功能開關技術理論與實踐結合的點點滴滴。 ...
  • 1.d3.shuffle D3.shuffle() 方法用於將數組中的元素隨機排序。它使用 Fisher–Yates 洗牌演算法,該演算法是無偏的,具有最佳的漸近性能(線性時間和常數記憶體)。 D3.shuffle() 方法的語法如下: d3.shuffle(array, [start, end]) 其中 ...