Electron 踩坑
来鹅厂做了俩常规项目(更新文件上传方式至 COS 及修改移动端顶部 UI)后参与了文档 App 的桌面 Electron App 开发,在 UI 层上又是一个坑接一个坑。主要有下述几点:
- 实现适应于内置
React组件大小的BrowserWindow,同时保证首次加载时页面不会错乱 - 使自定义弹窗可拖拽并且内部表单组件可使用
- 在
BrowserWindow内弹出超出 Window 范围的菜单 - 跨端编译打包后发现 runtime 对不上
使 BrowserWindow 自适应 React 组件
我们知道 Electron 的 BrowserWindow 的默认尺寸为 800 × 600,虽然可以初始化设置弹窗大小,但是并不知道弹窗内容尺寸呀!于是乎,需要先隐藏弹窗直至 compsnentDidMount 时获取到 dialog 内容尺寸再设置 BrowserWindow 的大小并显示。
1 | // main-process 打开弹窗 |
1 | // renderer 页面在组件加载后设置宽高并返回消息显示 window |
拖拽窗口
官方解答
遇到的坑是设置好 dialog 内部 button/input 的 no-drag 后发现 dui(某鹅厂组件库)会直接在 body 下生成 DOM 节点,哪怕设置上了 dui-* 这样的通配符都没用,在 Windows 上点击事件还是穿透了组件,只好给整个内容的区域都打上了 -webkit-app-region: no-drag。
弹出超出 Window 的菜单
官方做法
设计觉得 Windows 下不好看,于是要自定义 BrowserWindow。
1 | // main-process 打开弹窗 |
1 | // renderer 渲染进程捕获触发元素 |
其中
1 | ipcRenderer.send('open-menu', x | 0, y | 0) |
非常重要 😂 因为 Electron 打开 menu 的 x & y 只认整型,而 getBoundingClientRect() 返回了浮点数,直接用就崩了……
区分「开发时」「编译时」和「运行时」
跨端开发的优势就是 Write Once, Run Everywhere。代码能贴近运行时判断就贴近运行时判断,不过为了开发和打包大小,有如下几个优化思路。
- 跨端开发 UI 需要调试查看其他端上的状态,所以会需要一个全局的样式开关,目前只区分了
macOS和Windows,写作开发时只需要按需加1
2// constants/setting.ts
const useMacStyle = process.platform === 'darwin'!取反就可以方便切换样式了,process.platform是啥?这就是编译时了。 - 编译时需要确定目标对象,一般会写成不同脚本或者是一个脚本里根据
platform分发并写入进程参数,为了锁死各种依赖关系,假设某处写了process.platform === 'darwin如果platform不符合就会直接剪枝掉后面的部分。 - 而运行时就广泛得多,比如关闭所有窗口时默认退出 App。再比如根据系统类型开启不同的提示文本,这些都需要运行时判断,虽然也可以直接编译时判断,但终究不够灵活。
1
2
3
4
5
6
7import os from 'os'
import { app } from 'electron'
app.on('window-all-closed', () => {
if (os.platform() !== 'darwin') {
app.quit()
}
})
__结论__:类似于配置下发的流程,如果是偏开发侧的内容可以在一处统一管理,如果是偏向本地系统的功能可以根据实际运行环境开闭,做到尽量少依赖于编译时以求在多端最大化复用代码逻辑。
To be continued……




