以下是一些 Pinia 的其他高階功能: storeToRefs():響應式解構倉庫,保證解構出來的數據是響應式的數據。 狀態持久化:Pinia 並沒有內置的狀態持久化功能,但你可以使用第三方庫或自定義插件來實現狀態的持久化。例如,你可以使用 localStorage 或 sessionStorag ...
以下是一些 Pinia 的其他高階功能:
storeToRefs()
:響應式解構倉庫,保證解構出來的數據是響應式的數據。- 狀態持久化:Pinia 並沒有內置的狀態持久化功能,但你可以使用第三方庫或自定義插件來實現狀態的持久化。例如,你可以使用
localStorage
或sessionStorage
來將狀態保存在客戶端。 - 插件系統: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
進行持久化存儲。
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
)
以下示例是對官方示例,進行優化的版本。
(1)安裝js-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;
暫時沒有更多辣~