不使用 ipc 实现 electron 多窗口 ui state 同步更新的一种方法

2023-03-07 23:09:04 +08:00
 travisyang

electron 多窗口的开发很费劲,如果你想让一份数据在不同的窗口中显示,并且实现数据修改后,ui 同步更改的功能,用 ipc 显然是费时费力的。网上关于两个窗口 ui 同步的文章也很少。

因为我工作中用的 react 和 mobx 较多,就想着一个 mobx 的 class 实例,能不能让两个窗口公用。

在 github mobx 仓库有一个 issue ,https://github.com/mobxjs/mobx/issues/1644

但是作者并没有给出实现,只是提到了因为不同窗口的 mobx 实例不同,所以做不到同步。

于是我想到能不能让其他的窗口(例如子窗口)使用来自于另一个窗口的 mobx

在窗口 A 中

import observer from 'mobx-react-lite';
import ReactDOM from 'react-dom';
window.observer = observer;
window.ReactDOM = ReactDOM;
window.store = store;

在窗口 B 中

const {observer, ReactDOM, store} = windowA;
const Component = observer(()=>{
  return <div>{store.something}</div>;
});
ReactDOM.render(<Component/>, container);

这样便可以用同一份数据,实现两个窗口的 ui 同步。

效果图:

demo 链接: https://github.com/wxydev1/electron-sync-state

1287 次点击
所在节点    程序员
5 条回复
zsj1029
2023-03-08 13:26:07 +08:00
Nice 非常好的思路,原理是什么呢,两个窗口两个实例独立内存运行时
window 对象支持相互引用吗
travisyang
2023-03-08 14:24:09 +08:00
@zsj1029 虽然是两个独立内存,但是通过 window 对象,两者可以拿到互相的内容。

window 对象支持互相引用,通过 window.open 函数的返回值可以拿到窗口对象的引用,也可以通过 window.opener 得到打开窗口的那个窗口

const childWindow = window.open();

const parentWindow = window.opener;

因此我尝试用同一个 ReactDOM 引用去渲染不同窗口的视图,发现真的可以实现同步。
lizhenda
2023-03-08 14:33:53 +08:00
window.open 打开的子窗口才可以这么玩的吧,这个 windows 是对象是 electron 帮你在创建窗口时传递的。如果是主进程创建的其它不相关的窗口,那就没办法了。适用性偏低。不如自己把 ipc 和 proxy 封装下。状态管理本质就是 proxy 调用 ipc 去更新而已。
travisyang
2023-03-08 14:56:21 +08:00
@lizhenda 好的,我突然发现我这种方式在子窗口的组件中不能用 react hook 了,感觉确实有局限性。
travisyang
2023-03-08 15:33:52 +08:00
@lizhenda 其实我觉得最简单的还是主窗口用 BrowserWindow 创建,其他窗口通过主窗口的渲染进程打开,将 mobx store 对象暴露在 window 上,然后修改互相的 window.store 的属性值,就能实现视图同步。但这样的问题在于多个窗口就要有多个 store 对象,而不是一个 store 对象可以被多个窗口监听到。我本来想表达这个主题,刚刚发现这种局限性很大😢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/922059

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX