模态窗口、父子窗口和 alwaysOnTop 的层级怎么处理?
考察点
parent/modal的平台差异- 置顶窗口把对话框挡在后面一类问题
参考答案
1. 父子窗口
const child = new BrowserWindow({
parent: mainWindow, // 子窗口跟着父窗口最小化、关闭
modal: true, // 模态:父窗口在子窗口关掉前不能操作
width: 480,
height: 320,
show: false,
});
效果:
- 父窗口关闭,子窗口一起关
- 父窗口最小化,子窗口跟着隐藏
modal: true时,用户无法把焦点点回父窗口
macOS 上模态更接近 sheet 的交互预期;Windows 上是禁用父窗口。Linux 视桌面环境而定,模态不一定可靠,关键流程要在应用内再挡一层,不能只靠操作系统。
2. alwaysOnTop
win.setAlwaysOnTop(true, 'floating'); // level:normal / floating / screen-saver 等
置顶级别高于普通窗口,也常常高于自己的 dialog.showMessageBox。现象是:提示框跑到置顶窗口后面,用户以为应用卡死。
处理:
- 弹出对话框前先
setAlwaysOnTop(false),关完再恢复 - 或者把对话框的
parent设成这个置顶窗口 - 录屏小窗、悬浮球才需要一直置顶,主界面不要全局置顶
3. 多个子窗口
BrowserWindow.getFocusedWindow() 在模态打开时可能是子窗口。IPC 里不要假设“焦点窗口就是主窗口”,用 event.sender 反查。
关闭顺序:如果业务要求“设置没保存不能关主窗口”,在父窗口的 close 里检查子窗口状态,而不是只依赖 modal。
面试话术
附属窗口用 parent,需要卡住父窗口再用 modal。alwaysOnTop 会把系统对话框压到后面,弹框前先取消置顶或把对话框挂到这个窗口上。Linux 上模态不完全可靠。IPC 用 event.sender 找窗口,不用焦点窗口猜。
常见追问
- 子窗口能有自己的 preload 吗? 可以,而且应该更小。设置窗口不必继承主窗口的全部 API。
- 全屏窗口再开模态会怎样? macOS 全屏空间里子窗口可能跑到另一桌面。全屏时改用页面内对话框更稳。