V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
travisyang
V2EX  ›  程序员

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

  •  
  •   travisyang ·
    wxydev1 · 2023-03-07 23:09:04 +08:00 · 1538 次点击
    这是一个创建于 629 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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

    5 条回复    2023-03-08 15:33:52 +08:00
    zsj1029
        1
    zsj1029  
       2023-03-08 13:26:07 +08:00
    Nice 非常好的思路,原理是什么呢,两个窗口两个实例独立内存运行时
    window 对象支持相互引用吗
    travisyang
        2
    travisyang  
    OP
       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
        3
    lizhenda  
       2023-03-08 14:33:53 +08:00
    window.open 打开的子窗口才可以这么玩的吧,这个 windows 是对象是 electron 帮你在创建窗口时传递的。如果是主进程创建的其它不相关的窗口,那就没办法了。适用性偏低。不如自己把 ipc 和 proxy 封装下。状态管理本质就是 proxy 调用 ipc 去更新而已。
    travisyang
        4
    travisyang  
    OP
       2023-03-08 14:56:21 +08:00
    @lizhenda 好的,我突然发现我这种方式在子窗口的组件中不能用 react hook 了,感觉确实有局限性。
    travisyang
        5
    travisyang  
    OP
       2023-03-08 15:33:52 +08:00
    @lizhenda 其实我觉得最简单的还是主窗口用 BrowserWindow 创建,其他窗口通过主窗口的渲染进程打开,将 mobx store 对象暴露在 window 上,然后修改互相的 window.store 的属性值,就能实现视图同步。但这样的问题在于多个窗口就要有多个 store 对象,而不是一个 store 对象可以被多个窗口监听到。我本来想表达这个主题,刚刚发现这种局限性很大😢
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1309 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 17:50 · PVG 01:50 · LAX 09:50 · JFK 12:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.