作者: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、簡書、開源中國、部落格園 關注我們。