作者: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. 創建窗口配置
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、簡書、開源中國、博客園 關注我們。