Electron 快速上手
对小白来说,electorn就是一个能将前端webapp打包成一个桌面应用的工具。
Electron的基础概念
此框架在架构上非常相似于一个现代的网页浏览器。每个 Electron 应用都有一个单一的主进程,作为应用程序的入口点。 主进程在 Node.js 环境中运行,这意味着它具有 require
模块和使用所有 Node.js API 的能力。
主进程
主进程的主要目的是使用 BrowserWindow
模块创建和管理应用程序窗口。
electron将一个页面加载进应用窗口的模块:
app
模块(控制应用程序的事件生命周期)。BrowserWindow
模块(创建和管理应用程序窗口)
const { app, BrowserWindow } = require('electron')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js') // 预加载脚本
}
})
win.loadFile('index.html') // 将index.html加载进一个新的BrowserWindow实例
// 或者 win.loadURL('https://github.com')Ï
const contents = win.webContents // 从主进程用 window 的 webContent 对象与网页内容进行交互。
console.log(contents)
}
// 调用createWindow()函数来打开窗口。
// 在 app 模块的 ready 事件被激发后才能创建浏览器窗口。 使用app.whenReady() API来监听此事件,在成功后调用 `createWindow()`
app.whenReady().then(() => {
createWindow()
})
BrowserWindow
的每个实例创建一个应用程序窗口,且在单独的渲染器进程中加载一个网页。当一个 BrowserWindow
实例被销毁时,与其相应的渲染器进程也会被终止。
关闭所有页面后推出程序(windows、Linux)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit() // if the user is not on macOS (darwin)
})
如果没有窗口,则打开一个窗口(macOS)
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
渲染器进程
- 以一个 HTML 文件作为渲染器进程的入口点。
- 使用层叠样式表 (Cascading Style Sheets, CSS) 对 UI 添加样式。
- 通过
<script>
元素可添加可执行的 JavaScript 代码。
渲染器无权直接访问 require
或其他 Node.js API。
预加载脚本
预加载脚本在渲染器进程加载之前加载,并有权访问两个 渲染器全局 (例如 window
和 document
) 和 Node.js 环境。预加载脚本可以在 BrowserWindow
构造方法中的 webPreferences
选项里被附加到主进程。
// preload.js
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
语境隔离(Context Isolation)意味着预加载脚本与渲染器的主要运行环境是隔离开来的,以避免泄漏任何具特权的 API 到您的网页内容代码中。
使用 contextBridge
模块来安全地实现交互:
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
desktop: true
})
此功能对两个主要目的來說非常有用:
- 通过暴露
ipcRenderer
模块于渲染器中,可以使用 进程间通讯 ( inter-process communication, IPC ) 来从渲染器触发主进程任务 ( 反之亦然 ) 。 - 如果您正在为远程 URL 上托管的现有 web 应用开发 Electron 封裝,则您可在渲染器的
window
全局变量上添加自定义的属性,好在 web 客户端用上仅适用于桌面应用的设计逻辑 。