Tauri+Pinia 实现窗口间数据同步
我是一名初学者,我在使用Tauri+vue3+pinia开发桌面应用的时候,发现窗口间的Pinia对象是独立的,但是我现在的需求是,Pinia中的部分数据是可以窗口间同步的(比如:有一个count属性,当其中一个窗口改变时,其他窗口同步改变)。
这是我目前的实现方法
import { createPinia } from 'pinia';
import { emit, listen, type Event } from '@tauri-apps/api/event';
import { appWindow } from '@tauri-apps/api/window';
export default defineNuxtPlugin((nuxtApp: any) => {
const pinia = createPinia();
nuxtApp.vueApp.use(pinia)
pinia.use(syncDataWithMainWindow);
})
/** 窗口间数据同步 所有数据和主窗口同步 */
export async function syncDataWithMainWindow(context: any) {
watch(context.store, () => {
if (!context.store.watchEnabled.value) {
context.store.setWatchEnabled(true)
return;
}
emit('syncStore', context.store);
}, { flush: 'post' });
listen('syncStore', (event: Event<any>) => {
if (context.store.label.value === event.payload.label._value) return; // 忽视自己发送的事件
// 非主窗口停止监听转发数据,只有主窗口接收到数据会进行转发
if (appWindow.label !== 'main') {
context.store.setWatchEnabled(false);
}
context.store.window_sync_source.value = event.payload.label._value; // 记录数据来源
context.store.syncCount.value = event.payload.syncCount._value
})
}
目前存在的问题是,在代码同步完成后,会触发watch,然后陷入同步的循环,虽然我做了watch开关处理,但是窗口间的数据同步本身就是非同步的过程,这样做依然会陷入循环,而且这样做感觉埋了一个惊天大bug。
期望的数据交换:
大家有没有更好的方法实现😭😭
曾经的尝试:
#region 所有窗口之间相互同步,资源消耗大
export async function syncDataBetweenWindows(context: any) {
await initSync(context);
updateSync(context);
}
function initSync(context: any) {
return new Promise((res, rej) => {
let timeout = setTimeout(() => {
rej(false);
throw new Error("页面初始化获取全局Store超时");
}, 3000);
once('initStoreSync', (event: any) => {
sync(event, context);
clearTimeout(timeout);
res(true);
})
listen('initStore', (event: any) => {
if (event.payload.label === appWindow.label) return;
emit('initStoreSync', {
data: {
store: context.store,
label: appWindow.label
}
})
})
emit('initStore', { label: appWindow.label });
})
}
function updateSync(context: any) {
watch(context.store, () => {
if (context.listenUpdate) {
context.listenUpdate = false;
return;
}
emit('storeSync', {
data: {
store: context.store,
label: appWindow.label
}
})
})
listen('storeSync', async (event: any) => {
sync(event, context);
})
}
function sync(event: any, context: any) {
if (event.payload.data.label == appWindow.label) return;
for (const key in event.payload.data.store) {
if (!Object.prototype.hasOwnProperty.call(event.payload.data.store, key)) continue;
if (key.substring(0, 4) != 'sync') continue;
context.listenUpdate = true;
context.store[key].value = event.payload.data.store[key]._value;
console.log('数据同步');
}
}
#endregion
所有窗口之间的数据同步,在store中,使用sync开头的属性变量名会被标记为需要同步的数据。这样做同样会陷入循环,导致程序崩溃,而且感觉这样做很消耗资源。
解决方法:不用vue的监听数据的更新,Pinia有一个$onAction函数,用来监听Store的Action是否被调用