引入
demo項(xiàng)目地址
我們之前寫(xiě)了一個(gè)自動(dòng)同步pinia狀態(tài)的插件,可以參考如下文章
electron+vue3全家桶+vite項(xiàng)目搭建【16】electron多窗口,pinia狀態(tài)無(wú)法同步更新問(wèn)題解決
這里面有一個(gè)較大的弊端,就是pinia中的store,只要其中的某個(gè)屬性修改,就會(huì)觸發(fā)這個(gè)store的全量更新,當(dāng)我們有一些狀態(tài)頻繁更新的時(shí)候,就會(huì)影響性能,并且有些窗口中的store其實(shí)是不需要同步的,但我們無(wú)法進(jìn)行精準(zhǔn)的控制,而且為了保證多個(gè)窗口間的同步一致,我們做了很多兜底處理。
現(xiàn)在提供另一個(gè)思路,我們不被動(dòng)的自動(dòng)更新同步store的狀態(tài),而是通過(guò)擴(kuò)展store的actions方法,讓業(yè)務(wù)主動(dòng)調(diào)用方法時(shí)來(lái)主動(dòng)通知其他窗口完成同步。
實(shí)現(xiàn)效果如下
可以看到,只有當(dāng)我主動(dòng)觸發(fā)同步方法時(shí),才會(huì)進(jìn)行窗口間的狀態(tài)同步
實(shí)現(xiàn)步驟
1.自定義pinia插件
自定義pinia插件,擴(kuò)展store,擴(kuò)展一個(gè)stateSync方法
-
我們先聲明一個(gè)stateSync方法,然后在store初始化的時(shí)候重寫(xiě)該方法
-
src\store\plugins\shareStoreByActionPlugin.ts文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-678190.html
import { ipcRenderer } from "electron";
import cacheUtils from "@/utils/cacheUtils";
import { PiniaPluginContext } from "pinia";
// 設(shè)置本地store緩存的key
const STORE_CACHE_KEY_PREFIX = "store_";
declare module "pinia" {
export interface PiniaCustomProperties {
// 通知主進(jìn)程讓所有窗口同步pinia的狀態(tài)
stateSync(): void;
}
}
// 處理electron多窗口,pinia共享問(wèn)題
export function shareStorePlugin({ store }: PiniaPluginContext) {
// 初始化本地緩存版本
const storeName: string = store.$id;
// 初始化store
initStore(store);
// 重寫(xiě)狀態(tài)同步方法
store.stateSync = () => {
updateStoreSync(stringify(store.$state), storeName);
};
// 監(jiān)聽(tīng)數(shù)據(jù)同步修改
ipcRenderer.on(
"pinia-store-set",
(event, targetStoreName: string, jsonStr: string) => {
console.log("被動(dòng)更新哦");
// 監(jiān)聽(tīng)到狀態(tài)改變后,同步更新?tīng)顟B(tài)
if (storeName === targetStoreName) {
// 補(bǔ)充版本號(hào)是否重置標(biāo)識(shí)
console.log("被動(dòng)更新?tīng)顟B(tài):" + storeName);
const obj = JSON.parse(jsonStr);
const keys = Object.keys(obj);
const values = Object.values(obj);
/// 更新各個(gè)key對(duì)應(yīng)的值的狀態(tài)
for (let i = 0; i < keys.length; i++) {
changeState(store.$state, keys[i], values[i]);
}
}
}
);
}
/**
* 狀態(tài)更新同步
* @param stateJsonStr 序列化的狀態(tài)修改字符串
* @param storeName 修改的狀態(tài)的名稱
*/
function updateStoreSync(stateJsonStr: string, storeName: string) {
// 通知主線程更新
ipcRenderer.invoke("pinia-store-change", storeName, stateJsonStr);
// 更新本地緩存的store
cacheUtils.set(STORE_CACHE_KEY_PREFIX + storeName, stateJsonStr);
}
/**
* 修改state的值
* 補(bǔ)充 如果反序列化的字段是map類(lèi)型,需要額外處理
*/
function changeState(state: any, key: any, value: any) {
if (state[key] instanceof Map) {
if (value instanceof Array) {
state[key] = new Map(value);
} else {
state[key] = new Map(Object.entries(value as object));
}
} else {
state[key] = value;
}
}
/**
* 初始化狀態(tài)對(duì)象
* @param store
*/
function initStore(store: any) {
const cacheKey = STORE_CACHE_KEY_PREFIX + store.$id;
// 從本地緩存中讀取store的值
const stateJsonStr = cacheUtils.get(cacheKey);
if (stateJsonStr) {
const stateCache = JSON.parse(stateJsonStr);
const keys = Object.keys(stateCache);
const values = Object.values(stateCache);
/// 更新各個(gè)key對(duì)應(yīng)的值的狀態(tài)
for (let i = 0; i < keys.length; i++) {
changeState(store.$state, keys[i], values[i]);
}
}
}
/**
* 2023/07/03 自定義序列化方式, 處理ts中map類(lèi)型/對(duì)象序列化后為 {} 的情況
*/
function stringify(obj: any): string {
return JSON.stringify(cloneToObject(obj));
}
// 將字段包含map的對(duì)象轉(zhuǎn)為json對(duì)象的格式
function cloneToObject(obj: any): any {
let newObj: any = obj;
if (obj instanceof Map) {
return Object.fromEntries(obj);
}
if (obj instanceof Object) {
newObj = {};
const keys = Object.keys(obj);
const values = Object.values(obj);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = values[i];
newObj[key] = cloneToObject(value);
}
}
if (obj instanceof Array) {
newObj = [];
for (let i = 0; i < obj.length; i++) {
newObj[i] = cloneToObject(obj[i]);
}
}
return newObj;
}
然后我們主動(dòng)在pinia的初始化中使用插件文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-678190.html
- src\store\index.ts
import { createPinia } from "pinia";
// import { shareStorePlugin } from "./plugins/shareStorePlugin";
import { shareStorePlugin } from "./plugins/shareStoreByActionPlugin";
const pinia = createPinia();
// 添加狀態(tài)共享插件
pinia.use(shareStorePlugin);
export default pinia;
2.主進(jìn)程補(bǔ)充同步處理
- electron\main\index.ts
- 主進(jìn)程中添加pinia監(jiān)聽(tīng),遍歷通知窗口進(jìn)行pinia的更新
/**pinia多窗口共享 */
ipcMain.handle(
"pinia-store-change",
(
event,
storeName: string,
jsonStr: string,
) => {
// 遍歷window執(zhí)行
for (const currentWin of BrowserWindow.getAllWindows()) {
const webContentsId = currentWin.webContents.id;
if (webContentsId !== event.sender.id && !currentWin.isDestroyed()) {
currentWin.webContents.send(
"pinia-store-set",
storeName,
jsonStr
);
}
}
}
);
到了這里,關(guān)于electron+vue3全家桶+vite項(xiàng)目搭建【16.1】electron多窗口,pinia狀態(tài)同步,擴(kuò)展store方法,主動(dòng)同步pinia的狀態(tài)【推薦】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!