作者:Kurosaki
本文主要讲解Electron
窗口的 API
和一些在开发之中遇到的问题。
官方文档 虽然比较全面,但是要想开发一个商用级别的桌面应用必须对整个 Electron API
有较深的了解,才能应对各种需求。
1. 创建窗口
通过BrowserWindow
,来 创建 或者 管理 新的浏览器窗口,每个浏览器窗口都有一个进程来管理。
1.1. 简单创建窗口
const { BrowserWindow } = require('electron');
const win = new BrowserWindow();
win.loadURL('https://github.com');
效果如下:
1.1.2. 优化
问题:electron
的 BrowserWindow
模块在创建时,如果没有配置 show:false
,在创建之时就会显示出来,且默认的背景是白色;然后窗口请求 HTML
,会出现视觉闪烁。
解决
const { BrowserWindow } = require('electron');
const win = new BrowserWindow({ show:false });
win.loadURL('https://github.com');
win.on('ready-to-show',()=>{
win.show();
})
两者对比有很大的区别
1.2. 管理窗口
所谓的管理窗口,相当于主进程可以干预窗口多少。
- 窗口的路由跳转
- 窗口打开新的窗口
- 窗口大小、位置等
- 窗口的显示
- 窗口类型(无边框窗口、父子窗口)
- 窗口内
JavaScript
的node
权限,预加载脚本等 - ....
这些个方法都存在于BrowserWindow
模块中。
1.2.1. 管理应用创建的窗口
BrowserWindow
模块在创建窗口时,会返回 窗口实例,这些 窗口实例 上有许多功能方法,我们利用这些方法,管理控制这个窗口。
在这里使用Map
对象来存储这些 窗口实例。
const BrowserWindowsMap = new Map<number, BrowserWindow>()
let mainWindowId: number;
const browserWindows = new BrowserWindow({ show:false })
browserWindows.loadURL('https://github.com')
browserWindows.once('ready-to-show', () => {
browserWindows.show()
})
BrowserWindowsMap.set(browserWindow.id, browserWindow)
mainWindowId = browserWindow.id // 记录当前窗口为主窗口
窗口被关闭,得把Map
中的实例删除。
browserWindow.on('closed', () => {
BrowserWindowsMap?.delete(browserWindowID)
})
1.2.2. 管理用户创建的窗口
主进程可以控制窗口许多行为,这些行为会在后续文章一一列举;以下以主进程控制窗口建立新窗口的行为为例。
使用new-window
监听新窗口创建
// 创建窗口监听
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
/** @params {string} disposition
* new-window : window.open调用
* background-tab: command+click
* foreground-tab: 右键点击新标签打开或点击a标签target _blank打开
* /
})
注:关于disposition
字段的解释,移步electron文档、electron源码、chrome 源码
扩展new-window
经过实验,并不是所有新窗口的建立, new-window
都能捕捉到的。
以下方式打开的窗口可以被new-window
事件捕捉到
window.open('https://github.com')
<a href='https://github.com' target='__blank'>链接</a>
**
渲染进程中使用BrowserWindow
创建新窗口,不会被 new-window
事件捕捉到
**
const { BrowserWindow } = require('electron').remote
const win = new BrowserWindow()
win.loadURL('https://github.com')
渲染进程访问 _remote_
_,主进程需配置enableRemoteModule:true _
使用这种方式同样可以打开一个新的窗口,但是主进程的new-window捕捉不到。
应用new-window
new-window
控制着窗口新窗口的创建,我们利用这点,可以做到很多事情;比如链接校验、浏览器打开链接等等。默认浏览器打开链接代码如下:
import { shell } from 'electron'
function openExternal(url: string) {
const HTTP_REGEXP = /^https?:\/\//
// 非http协议不打开,防止出现自定义协议等导致的安全问题
if (!HTTP_REGEXP) {
return false
}
try {
await shell.openExternal(url, options)
return true
} catch (error) {
console.error('open external error: ', error)
return false
}
}
// 创建窗口监听
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
if (disposition === 'foreground-tab') {
// 阻止鼠标点击链接
event.preventDefault()
openExternal(url)
}
})
关于 _shell_
_模块,可以查看官网 https://www.electronjs.org/docs/api/shell_
_
1.3. 关闭窗口
**close**
事件和 **closed**
事件close
事件在窗口将要关闭时之前触发,但是在 DOM
的 beforeunload
和 unload
事件之前触发。
// 窗口注册close事件
win.on('close',(event)=>{
event.preventDefault() // 阻止窗口关闭
})
closed
事件在窗口关闭后出触发,但是此时的窗口已经被关闭了,无法通过 event.preventDefault()
来阻止窗口关闭。
win.on('closed', handler)
主进程能够关闭窗口的 API
有很多,但都有各自的利弊。
1.3.1. win.close()
关于这个 API
的利弊
- 如果当前窗口实例注册并阻止
close
事件,将不会关闭页面,而且也会 阻止计算机关闭(必须手动强制退出); - 关闭页面的服务,如
websocket
,下次打开窗口,窗口中的页面会 重新渲染; - 通过这个
API
触发的close
事件在unload
和beforeunload
之前触发,通过这点可以实现 关闭时触发弹窗;
完整代码在github:electron-playground
- 会被
closed
事件捕捉到。
1.3.2. win.destroy()
- 强制退出,无视
close
事件(即:无法通过event.preventDefault()
来阻止); - 关闭页面,以及页面内的服务,下次打开窗口,窗口中的页面会重新渲染;
- 会被
closed
事件捕捉到。
1.3.3. win.hide()
这个隐藏窗口。
- 隐藏窗口,会触发
hide
和blur
事件,同样也是可以通过event.preventDefault()
来阻止 - 只是隐藏窗口,通过
win.show()
,可以将窗口显现,并且会保持原来的窗口,里面的服务也不会挂断
2. 主窗口隐藏和恢复
2.1. 主窗口
2.1.1. 为什么需要 主窗口?
一个应用存在着许多的窗口,需要一个窗口作为 主窗口,如果该窗口关闭,则意味着整个应用被关闭。
场景:在应用只有一个页面的时,用户点击关闭按钮,不想让整个应用关闭,而是隐藏;
例如:其他的APP,像微信,QQ等桌面端。
利用上文中提到的关闭窗口的 API
,我们实现一个主窗口的隐藏和恢复。
改造一下 close
事件
let mainWindowId: number // 用于标记主窗口id
const browserWindow = new BrowserWindow()
// 记录下主窗口id
if (!mainWindowId) {
mainWindowId = browserWindow.id
}
browserWindow.on('close', event => {
// 如果关闭的是主窗口,阻止
if (browserWindow.id === mainWindowId) {
event.preventDefault()
browserWindow.hide()
}
})
2.1.2. 恢复主窗口显示
能隐藏,就能恢复。
const mainWindow = BrowserWindowsMap.get(mainWindowId)
if (mainWindow) {
mainWindow.restore()
mainWindow.show()
}
**mainWindow.show()**
方法:功能如其名,就是“show出窗口”。
为什么要是有 _mainWindow.restore()_
_?__windows_
_下如果 _hide_
_之后不调用 _show_
_方法而是只调用 _restore_
_方法就会导致页面挂住不能用
2.1.3. 强制关闭主窗口
有些场景下,可能需要的强制退出,附上代码:
const mainWindow = BrowserWindowsMap.get(mainWindowId)
if (mainWindow) {
mainWindowId = -1
mainWindow.close()
}
存在的问题
我们改变了 Electron
窗口的既定行为,就会有许多场景下会有问题
问题一:因为阻止了 close
事件,导致 关机 时无法关闭 主窗口,可以使用如下代码
app.on('before-quit', () => {
closeMainWindow()
})
在 macOS
Linux
Windows
下都可以。
问题二:为避免启动 多个应用
app.on('second-instance', () => {
const mainWindow = BrowserWindowsMap.get(mainWindowId)
if (mainWindow) {
mainWindow.restore()
mainWindow.show()
}
})
在 macOS
Linux
Windows
下都可以
问题三:首次启动应用程序、尝试在应用程序已运行时或单击 应用程序 的 坞站 或 任务栏图标 时重新激活它
app.on('activate', () => {
if (mainWindow) {
mainWindow.restore()
mainWindow.show()
}
})
只应用于macOS
下
问题四: 双击托盘图标 打开APP
tray.on('double-click', () => {
if (mainWindow) {
mainWindow.restore()
mainWindow.show()
}
})
这样每个环节的代码都有,即可实现,具体代码可参见链接
3. 窗口的聚焦和失焦
3.1. 聚焦
3.1.1. 创建窗口时配置
const { BrowserWindow } = require('electron');
const win = new BrowserWindow();
win.loadURL('https://github.com')
focusable:true
窗口便可聚焦,便可以使用聚焦的 API
focusable:false
在 Windows
中设置 focusable: false
也意味着设置了skipTaskbar: true
. 在 Linux
中设置 focusable: false
时窗口停止与 wm
交互, 并且窗口将始终置顶;
以下讨论的情况仅为focusable:true
情况下
const { BrowserWindow } = require('electron');
const win = new BrowserWindow() // focusable:true 为默认配置
罗列了一下 API
3.1.2. 关于聚焦的API
API | 功能 |
---|---|
BrowserWindow.getFocusedWindow() | 来获取聚焦的窗口 |
win.isFocused() | 判断窗口是否聚焦 |
win.on('focus',handler) | 来监听窗口是否聚焦 |
win.focus() | 手动聚焦窗口 |
3.1.3. 其他API副作用和聚焦有关的:
API | 功能 |
---|---|
win.show() | 显示窗口,并且聚焦于窗口 |
win.showInactive() | 显示窗口,但是不会聚焦于窗口 |
3.2. 失焦
3.2.1. 关于失焦的api
API | 功能 |
---|---|
win.blur() | 取消窗口聚焦 |
win.on('blur',cb) | 监听失焦 |
3.2.2. 其他api
副作用和失焦有关的:
api | 功能 |
---|---|
win.hide() | 隐藏窗口,并且会触发失焦事件 |
4. 窗口类型
4.1. 无边框窗口
4.1.1. 描述
无边框窗口是不带外壳(包括窗口边框、工具栏等),只含有网页内容的窗口
4.1.2. 实现
Windows
macOS
Linux
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ width: 800, height: 600, frame: false })
win.show()
在macOS
下,还有不同的实现方式,官方文档
4.1.3. macOS
下独有的无边框
- 配置
titleBarStyle: 'hidden'
返回一个隐藏标题栏的全尺寸内容窗口,在左上角仍然有标准的窗口控制按钮(俗称“红绿灯”)
// 创建一个无边框的窗口
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'hidden' })
win.show()
效果如下:
- 配置
titleBarStyle: 'hiddenInset'
返回一个另一种隐藏了标题栏的窗口,其中控制按钮到窗口边框的距离更大。
// 创建一个无边框的窗口
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
win.show()
效果如下:
配置titleBarStyle: 'customButtonsOnHover'
效果如下:
4.1.4. 窗口顶部无法拖拽的问题
虽然无边框窗口,很美观,可以自定义title;但是改变了Electron窗口顶部的默认行为,就需要使用代码来兼容它,实现其原来承担的功能。
出现上述情况,是因为在默认情况下, 无边框窗口是不可拖拽的。 应用程序需要在 CSS
中指定 -webkit-app-region: drag
来告诉 Electron
哪些区域是可拖拽的(如操作系统的标准标题栏),在可拖拽区域内部使用 -webkit-app-region: no-drag
则可以将其中部分区域排除。 请注意, 当前只支持矩形形状。完整文档
使用-webkit-app-region: drag
来实现拖拽,但是会导致内部的click
事件失效。这个时候可以将需要click
元素设置为-webkit-app-region: no-drag
。具体的细节 Electron
的issues
为了不影响窗口内的业务代码,这里拖拽的代码,应该在preload
触发。
preload
代码运行,在窗口代码运行之前
核心代码:
// 在顶部插入一个可以移动的dom
function initTopDrag() {
const topDiv = document.createElement('div') // 创建节点
topDiv.style.position = 'fixed' // 一直在顶部
topDiv.style.top = '0'
topDiv.style.left = '0'
topDiv.style.height = '20px' // 顶部20px才可拖动
topDiv.style.width = '100%' // 宽度100%
topDiv.style.zIndex = '9999' // 悬浮于最外层
topDiv.style.pointerEvents = 'none' // 用于点击穿透
// @ts-ignore
topDiv.style['-webkit-user-select'] = 'none' // 禁止选择文字
// @ts-ignore
topDiv.style['-webkit-app-region'] = 'drag' // 拖动
document.body.appendChild(topDiv) // 添加节点
}
window.addEventListener('DOMContentLoaded', function onDOMContentLoaded() {
initTopDrag()
})
在创建窗口时引用 preload
即可
const path = require('path')
const { BrowserWindow } = require('electron')
const BaseWebPreferences = {
nodeIntegration: true,
preload: path.resolve(__dirname, './windowType.js'), // 这里引用preload.js 路径
}
// 主窗口代码
const win = new BrowserWindow({ webPreferences: BaseWebPreferences, frame: false, titleBarStyle: 'hiddenInset' })
win.loadURL('https://github.com')
便可实现窗口顶部拖拽
tips: 如果窗口打开了 _devtools_
_,窗口也是可以拖拽的,只不过这个拖拽体验不好_
4.2. 父子窗口
所谓的父子窗口,就是子窗口永远在父窗口之上,只要子窗口存在,哪怕位置不在父窗口上方,都是无法操作父窗口
const { BrowserWindow } = require('electron')
let top = new BrowserWindow()
let child = new BrowserWindow({ parent: top })
child.show()
top.show()
在 窗口之间通信 章节中介绍到父子窗口之间的通信;通过 getParentWindow
拿到父窗口的 类BrowserWindowProxy,通过 win.postMessage(message,targetOrigin)
实现通信
4.3. 模态窗口
模态窗口也是一种父子窗口,只不过展示会有不同
const { BrowserWindow } = require('electron')
let top = new BrowserWindow()
let child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
child.show()
})
5. 窗口之间的通信
实现窗口通信必须不影响窗口内的业务代码, jdk
等的注入
5.1. 主进程干预方式
主进程是可以干预渲染进程生成新的窗口的,只需要在创建窗口时,webContents
监听 new-window
import path from 'path'
import { PRELOAD_FILE } from 'app/config'
import { browserWindow } from 'electron';
const BaseWebPreferences: Electron.BrowserWindowConstructorOptions['webPreferences'] = {
nodeIntegration: true,
webSecurity: false,
preload: path.resolve(__dirname, PRELOAD_FILE),
}
// 创建窗口监听
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
event.preventDefault()
// 在通过BrowserWindow创建窗口
const win = new BrowserWindow({
show:false,
webPreferences: {
...BaseWebPreferences,
additionalArguments:[`--parentWindow=${browserWindow.id}`] // 把父窗口的id传过去
}
});
win.loadURl(url);
win.once('ready-to-show',()=>{
win.show()
})
})
在 preload.js
文件window.process.argv
,便能拿到父窗口的id,window.process.argv
是一个字符串数组,可以使用yargs来解析
preload.js
代码
import { argv } from 'yargs'
console.log(argv);
拿到了父窗口的 id
,封装一下通信代码,挂载到 window
上
/**
* 这个是用于窗口通信例子的preload,
* preload执行顺序在窗口js执行顺序之前
*/
import { ipcRenderer, remote } from 'electron'
const { argv } = require('yargs')
const { BrowserWindow } = remote
// 父窗口监听子窗口事件
ipcRenderer.on('communication-to-parent', (event, msg) => {
alert(msg)
})
const { parentWindowId } = argv
if (parentWindowId !== 'undefined') {
const parentWindow = BrowserWindow.fromId(parentWindowId as number)
// 挂载到window
// @ts-ignore
window.send = (params: any) => {
parentWindow.webContents.send('communication-to-parent', params)
}
}
应用一下试试看:
这种方法可以实现通信,但是太麻烦了。
5.2. 父子窗口通信
和主进程干预,通过ipc
通信方式差不多,只是利用父子窗口这点,不用通过additionalArguments
传递父窗口id
,在子窗口通过window.parent
,就可以拿到父窗口
browserWindow.webContents.on('new-window', (event, url, frameName, disposition) => {
event.preventDefault()
// 在通过BrowserWindow创建窗口
const win = new BrowserWindow({
show:false,
webPreferences:BaseWebPreferences,
parent:browserWindow // 添加父窗口
});
win.loadURl(url);
win.once('ready-to-show',()=>{
win.show()
})
})
弊端:子窗口永远在父窗口之上。
const path = require('path')
const { BrowserWindow } = require('electron')
const BaseWebPreferences = {
// // 集成node
nodeIntegration: true,
// // 禁用同源策略
// webSecurity: false,
// 预加载脚本 通过绝对地址注入
preload: path.resolve(__dirname, './communication2.js'),
}
// 主窗口代码
const parent = new BrowserWindow({ webPreferences: BaseWebPreferences, left: 100, top: 0 })
parent.loadURL(
'file:///' + path.resolve(__dirname, '../playground/index.html#/demo/communication-part2/main'),
)
parent.webContents.on('new-window', (event, url, frameName, disposition) => {
// 阻止默认事件
event.preventDefault()
// 在通过BrowserWindow创建窗口
// 子窗口代码
const son = new BrowserWindow({
webPreferences: BaseWebPreferences,
parent,
width: 400,
height: 400,
alwaysOnTop: false,
})
// son.webContents.openDevTools();
son.loadURL(
'file:///' +
path.resolve(__dirname, '../playground/index.html#/demo/communication-part2/client'),
)
})
preload.js
import { remote, ipcRenderer } from 'electron'
// 父窗口监听子窗口事件
ipcRenderer.on('communication-to-parent', (event, msg) => {
alert(msg)
})
const parentWindow = remote.getCurrentWindow().getParentWindow()
// @ts-ignore
window.sendToParent = (params: any) =>
parentWindow.webContents.send('communication-to-parent', params)
但是必须得是父子窗口,有弊端。
5.3. 使用window.open
终极方法
在 web
端,使用 window.open
会返回一个 windowObjectReference
,通过这个方法可以实现 postMessage
;但是在 Electron
端,把 window.open
方法重新定义了;使用 window.open
创建一个新窗口时会返回一个 BrowserWindowProxy
对象,并提供一个有限功能的子窗口.
MDN文档 Electron文档
const BrowserWindowProxy = window.open('https://github.com', '_blank', 'nodeIntegration=no')
BrowserWindowProxy.postMessage(message, targetOrigin)
代码精简,且需要的功能,即符合 BrowserWindow(options)
中 options
配置的,都可以使用 window.open
配置。
6. 全屏、最大化、最小化、恢复
6.1. 全屏
6.1.1. 创建时进入全屏
配置new BrowserWindow({ fullscreen:true })
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ fullscreen:true,fullscreenable:true })
win.loadURL('https://github.com')
6.1.2. 使用API
进入全屏
确保当前窗口的fullscreenable:true
,以下API
才能使用
win.setFullScreen(flag)
,设置全屏状态;win.setSimpleFullScreen(flag)
,macOS
下独有,设置简单全屏。
6.1.3. 全屏状态的获取
win.fullScreen
,来判断当前窗口是否全屏;win.isFullScreen()
,macOS
独有;win.isSimpleFullScreen()
,macOS
独有。
6.1.4. 全屏事件的监听
rezise
调整窗口大小后触发;enter-full-screen
窗口进入全屏状态时触发;leave-full-screen
窗口离开全屏状态时触发;enter-html-full-screen
窗口进入由HTML API 触发的全屏状态时触发;leave-html-full-screen
窗口离开由HTML API触发的全屏状态时触发。
6.1.5. HTML
API
无法和窗口联动问题
const path = require('path')
const { BrowserWindow } = require('electron')
const BaseWebPreferences = {
nodeIntegration: true,
preload: path.resolve(__dirname, './fullScreen.js'),
};
const win = new BrowserWindow({ webPreferences: BaseWebPreferences })
win.loadURL('file:///' + path.resolve(__dirname, '../playground/index.html#/demo/full-screen'))
使用按钮全屏和退出全屏是可以的,但是先点击左上角🚥全屏,再使用按钮退出全屏,是不行的。因为无法知道当前的状态是全屏,还是不是全屏。
解决办法:,将win.setFullScreen(flag)
方法挂载到窗口的window
上
加载这样一段preload.js代码即可
import { remote } from 'electron'
const setFullScreen = remote.getCurrentWindow().setFullScreen
const isFullScreen = remote.getCurrentWindow().isFullScreen
window.setFullScreen = setFullScreen
window.isFullScreen = isFullScreen
setFullScreen文档 https://www.electronjs.org/docs/api/browser-window#winsetfullscreenflag isFullScreen 文档https://www.electronjs.org/docs/api/browser-window#winisfullscreen
6.2. 最大化、最小化
6.2.1. 创建窗口配置
完整API文档
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ minWidth:300,minHeight:300,maxWidth:500,maxHeight:500,width:600,height:600 })
win.loadURL('https://github.com')
当使用 minWidth/maxWidth/minHeight/maxHeight
设置最小或最大窗口大小时, 它只限制用户。 它不会阻止您将不符合大小限制的值传递给 setBounds/setSize
或 BrowserWindow
的构造函数。
6.2.2. 相关事件
事件名称 | 触发条件 |
---|---|
maximize | 窗口最大化时触发 |
unmaximize | 当窗口从最大化状态退出时触发 |
minimize | 窗口最小化时触发 |
restore | 当窗口从最小化状态恢复时触发 |
6.2.3. 相关状态API
win.minimizable
窗口是否可以最小化win.maximizable
窗口是否可以最大化win.isMaximized()
是否最大化win.isMinimized()
是否最小化
6.2.4. 控制API
win.maximize()
使窗口最大化win.unmaximize()
退出最大化win.minimize()
使窗口最小化win.unminimize()
退出最小化
6.3. 窗口恢复
win.restore()
将窗口从最小化状态恢复到以前的状态。在前面的例子 主窗口隐藏和恢复也有用到这个api
7. 窗口各事件触发顺序
7.1. 窗口加载时
BrowserWindow实例:即 new BrowserWindow()
返回的实例对象
webContents: 即 BrowserWindow
实例中的 webContents
对象
webPreferences: 即 new BrowserWindow(options)
中 options
的 webPreferences
配置对象
从上到下,依次执行
环境 | 事件 | 触发时机 |
---|---|---|
webPreferences的preload | - | 在页面运行其他脚本之前预先加载指定的脚本 无论页面是否集成Node, 此脚本都可以访问所有Node API 脚本路径为文件的绝对路径。 |
webContents | did-start-loading | 当tab中的旋转指针(spinner)开始旋转时,就会触发该事件 |
webContents | did-start-navigation | 当窗口开始导航是,触发该事件 |
窗口中的JavaScript | DOMContentLoaded | 初始的 HTML 文档被完全加载和解析完成 |
窗口中的JavaScript | load | 页面资源全部加载完成之时 |
BrowserWindow 实例 | show | 窗口显示时触发时 |
webContents | did-frame-navigate | frame 导航结束时时 |
webContents | did-navigate | main frame 导航结束时时 |
BrowserWindow 实例 | page-title-updated | 文档更改标题时触发 |
webContents | page-title-updated | 文档更改标题时触发 |
webContents | dom-ready | 一个框架中的文本加载完成后触发该事件 |
webContents | did-frame-finish-load | 当框架完成导航(navigation)时触发 |
webContents | did-finish-load | 导航完成时触发,即选项卡的旋转器将停止旋转 |
webContents | did-stop-loading | 当tab中的旋转指针(spinner)结束旋转时,就会触发该事件 |
7.2. 窗口加载完毕,用户触发事件(不包括resize和move)
事件 | 作用 |
---|---|
page-title-updated | 文档更改标题时触发 |
blur | 当窗口失去焦点时触发 |
focus | 当窗口获得焦点时触发 |
hide | 窗口隐藏 |
show | 窗口显示 |
maximize | 窗口最大化时触发(mac是双击title) |
unmaximize | 当窗口从最大化状态退出时触发 |
enter-full-screen | 窗口进入全屏状态时触发 |
leave-full-screen | 窗口离开全屏状态时触发 |
enter-html-full-screen | 窗口进入由HTML API 触发的全屏状态时触发 |
leave-html-full-screen | 窗口离开由HTML API触发的全屏状态时触发 |
always-on-top-changed | 设置或取消设置窗口总是在其他窗口的顶部显示时触发。 |
app-command | window linux 独有 |
7.3. 用户移动窗口
- 移动窗口之前
will-move
; - 移动窗口中
move
; - 移动之后
moved
;
7.4. 用户改变窗口大小
- 改变之前
will-resize
; - 改变之后
resize
7.5. 窗口的内容异常事件(webContent
事件)
事件名 | 错误类型 |
---|---|
unresponsive | 网页变得未响应时触发 |
responsive | 未响应的页面变成响应时触发 |
did-fail-load | 加载失败,错误码 |
did-fail-provisional-load | 页面加载过程中,执行了window.stop() |
did-frame-finish-load | |
crashed | 渲染进程崩溃或被结束时触发 |
render-process-gone | 渲染进程意外失败时发出 |
plugin-crashed | 有插件进程崩溃时触发 |
certificate-error | 证书的链接验证失败 |
preload-error | preload.js 抛出错误 |
7.6. 窗口关闭(包括意外关闭)
- 关闭之前:触发主进程中注册的
close
事件 - 窗口内的
JavaScript
执行window.onbeforeunload
- 窗口内的
JavaScript
执行window.onunload
- 关闭之后:触发主进程中注册的
closed
事件
对 Electron 感兴趣?请关注我们的开源项目 Electron Playground,带你极速上手 Electron。我们每周五会精选一些有意思的文章和消息和大家分享,来掘金关注我们的 晓前端周刊。
我们是好未来 · 晓黑板前端技术团队。
我们会经常与大家分享最新最酷的行业技术知识。
欢迎来 知乎、掘金、Segmentfault、CSDN、简书、开源中国、博客园 关注我们。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。