前几天发了一个帖子关于如何实现 electron 多窗口开发,发现思路有点问题。今天又想到了可以用 localStorage+hook 的方式。浏览器 window 可以监听 storage 的变化。并用 mobx 来管理状态,当状态值发生变化的时候,往 localStorage 中写入新的序列化后的值。
有评论区大哥说可以封装一个 ipc 的 proxy 。 但是我觉得 ipc 这玩意还是太过复杂,不如把所有的逻辑都放在渲染进程写。
hook 代码
import { autorun, observable } from "mobx"; import { useEffect } from "react"; export const useLocalStorage = <T>(storageKey: string, fallbackState: T) => { const state = observable({ value: JSON.parse(localStorage.getItem(storageKey)) ?? fallbackState, }); autorun(() => { localStorage.setItem(storageKey, JSON.stringify(state.value)); }); const OnStorageUpdate= (e) => { const { key, newValue } = e; state.value = JSON.parse(newValue); }; useEffect(() => { localStorage.setItem(storageKey, JSON.stringify(state.value)); window.addEventListener("storage", onStorageUpdate); return () => { window.removeEventListener("storage", onStorageUpdate); }; }, [state.value, storageKey]); return [state.value]; };
主窗口
const App = observer(() => { const [store, setStore] = useLocalStorage("store", countStore); return ( <div> <h1>I am Main Window</h1> <button OnClick={() => { const win = window.open("child.html"); }} > Open Child Window </button> <div>store.count = {store.count}</div> <button OnClick={() => { store.count--; }} > minus- </button> <button OnClick={() => { store.count++; }} > plus+ </button> </div> ); });
子窗口
const Child = observer(() => { const [store, setStore] = useLocalStorage('store', null); return ( <div> <h1 OnClick={() => { store.count ++ }}>I am Child Window</h1> <div>store.count = {store.count}</div> </div> ); });
效果图
demo 链接:
![]() | 1 zsj1029 2023-03-15 16:41:25 +08:00 https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API hook 是不是基于这个 storage 事件实现 |
2 ruxuan1306 2023-03-15 16:51:59 +08:00 思路有意思学习了。但看起来 useLocalStorage 少返回一个 setStore ,我猜是引入 mobx 后例程忘改了。 |
![]() | 3 travisyang OP @ruxuan1306 确实少返回了一个 setStore ,不过 mobx 支持直接修改成员变量触发 ui 更新,所以返回一个值也够了 |
![]() | 4 travisyang OP @zsj1029 是的 |
5 snowKing66 2023-04-19 09:45:15 +08:00 思路很棒,但是如果要实际运用到工程项目中,我还有点疑问,如果采用这种方式作为窗口通信,不知道效率上跟 ipc 相比如何?因为安全性方便应该是不如 ipc |
![]() | 6 travisyang OP @snowKing66 效率上还没考虑过。其实用 ipc 的话也可以用同样的方式封装成一个 hook 。我一开始只是觉得 ipc 太麻烦了 |