现象
开发一个无边框窗口(frame = false),为元素设置hover样式后,鼠标移上元素,hover样式生效
鼠标快速移出目标元素区域,hover样式并没有消失,如下图所示
(此现象尤其发生在目标元素靠近窗口边缘时)
如果你在这个元素上安装了mouseleave或mouseout事件,那么同样的这两个事件也不会被触发
MAC下不存在这个问题(存疑)
根因
这是Electron的一个BUG,只发生在无边框窗口上
https://github.com/electron/electron/issues/611
并且这个BUG在2014年就被提出来了
2018年时被官方标记为wont fix了
【我也没有办法.gif】
其实根本原因就是Electron没有截获系统级的鼠标移动事件
如果我们开发的是原生应用,或想给Electron提交这个PR
那么就要捕获WM_MOUSELEAVE消息(Windows操作系统下)
需要注意的是,你不尝试追踪这个消息的话,这个消息是不会出现在windows的消息循环中的
Windows操作系统下有个API:TrackMouseEvent,就是是专门做这个事情的
方案
当然我们大部分时候还是希望能快速解决问题,
最简单、有效的方法就是不要使用无边框窗口,通过禁用缩放来达到无边框窗口的效果
代码如下:
if (!this.resizable) {
this.win.on("will-resize", (e, rect: Rectangle) => {
if (rect.width > this.width || rect.width < this.width || rect.height > this.height || rect.height < this.height) {
e.preventDefault()
}
})
this.win.setMaximizable(false)
}
关键逻辑就是,当用户拖动缩放窗口时,一旦窗口高度或宽度大于或小于指定的值后,就拒绝更改窗口大小。
注意:不允许缩放的窗口往往也是不允许最大化的,所以需要禁用窗口最大化setMaximizable(false),避免用户双击拖动区域(-webkit-app-region: drag;)最大化窗口。
这个方案带来的问题就是虽然窗口不允许缩放,但当鼠标移动到窗口边缘时,还是出现了缩放的鼠标样式:
如果不想使用这个方案,
那么开发者还可以在需要监控鼠标移出事件的dom元素上安装一个定时器,
在一个较短的时间内轮训判断鼠标是否还在其上,
一旦发现鼠标不在它上面了,就还原元素的样式
当然,这个方案就不能使用hover伪类了。