electron组成
electron由Node.js+Chromium+Native APIs构成。可以理解为,它是一个得到了Node.js和基于不同平台的Native APIs加强的Chromium浏览器,可以用来开发跨平台的桌面级应用。
主进程(mian process)
主进程,通常是值 main.js 文件,是每个 Electron 应用的入口文件。它控制着整个 App 的生命周期,从打开到关闭。 它也管理着原生元素比如菜单,菜单栏,Dock 栏,托盘等。 主进程负责创建 APP 的每个渲染进程。而且整个 Node API 都集成在里面。
每个 app 的主进程文件都定义在 package.json 中的 main 属性当中
在Chromium中, 这个进程被称为 "浏览器进程"。它在Electron被重新命名, 以避免与渲染器进程混淆。
渲染进程(renderer process)
渲染进程是应用内的一个浏览器窗口。与主进程不同的是,它能够同时存在多个而且运行在不一样的进程。而且它们也能够被隐藏。
在通常的浏览器内,网页通常运行在一个沙盒的环境挡住并且不能够使用原生的资源。 然而 Electron 的用户在 Node.js 的 API 支持下可以在页面中和操作系统进行一些低级别的交互。
项目工程(electron-vue)
模版
vue init simulatedgreg/electron-vue my-project
app
生命周期钩子
will-finish-launching 在应用完成基本启动进程之后触发
ready 当electron完成初始化后触发
window-all-closed 所有窗口都关闭的时候触发,在windows和linux里,所有窗口都退出的时候通常是应用退出的时候
before-quit 退出应用之前的时候触发
will-quit 即将退出应用的时候触发
quit 应用退出的时候触发
事件钩子
active(仅macOS)当应用处于激活状态时
browser-window-created 当一个BrowserWindow被创建的时候
browser-window-focus 当一个BrowserWindow处于激活状态的时候
...
BrowserWindow
创建窗口
new BrowserWindow([options])
//options除了可以设置窗口样式及功能,还涉及网页功能设置
事件钩子
closed 当窗口被关闭的时候
focus 当窗口被激活的时候
show 当窗口展示的时候
...
☎️ 主进程和renderer进程的通信
ipcMain模块是EventEmitter类的一个实例。 在主进程使用时,它处理异步并且接收来自于渲染进程(网页)的同步信息。 从渲染器进程发送的消息将被发送到该模块。
回复同步信息时,需要设置event.returnValue。
将异步消息发送回发件人,需要使用event.sender.send(...)。
方法:
ipcMain.on(channel, listener)
ipcMain.once(channel, listener)
ipcMain.removeListener(channel, listener)
ipcMain.removeAllListeners([channel])
ipcRenderer 是一个 EventEmitter 的实例。 你可以使用它提供的一些方法从渲染进程 (web 页面) 发送同步或异步的消息到主进程。 也可以接收主进程回复的消息。
方法:
ipcRenderer.on(channel, listener)
ipcRenderer.once(channel, listener)
ipcRenderer.removeListener(channel, listener)
ipcRenderer.removeAllListeners([channel])
ipcRenderer.send(channel[, arg1][, arg2][, ...])
ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])
ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])
在渲染进程中使用node
import os from 'os'
import fs from 'fs'
import async from 'async'
import path from 'path'
inspectAndDescribeFile(filePath, cb) {
let result = {
file: path.basename(filePath),
path: filePath,
type: ''
}
fs.stat(filePath, (err, stat) => {
if(err) {
cb(err)
}else{
if(stat.isFile()) {
result.type = 'file'
}
if(stat.isDirectory()) {
result.type = 'directory'
}
cb(err, result)
}
})
},
调试
1.渲染进程调试
chrome devtools
-
devtron:
npm install devtron --save-dev
在console中执行: require('devtron').install()
2.主进程调试
chrome://inspect
VS Code
打包
electron-builder OR electron-packager
builder 是在 packager 基础上的整合版,提供开发到部署一整套,生产各个平台可以执行文件、安装程序、软件签名、自动更新。
使用electron-builder 打包
npm run build
跨平台打包:
/*package.json*/
//打包mac
node .electron-vue/build.js && electron-builder --mac
//打包win
node .electron-vue/build.js && electron-builder --win
//打包linux
node .electron-vue/build.js && electron-builder --linux
//全部打包
node .electron-vue/build.js && electron-builder --platform=all
项目迁移
- 将原有项目src文件夹下的文件迁移至renderer目录下
⚠️ 注意事项
注意拖拽事件
路由使用hash模式 (electron在生产环境下使用的是file://协议)
-
跨域问题:
mainWindow = new BrowserWindow({ webPreferences: {webSecurity: false}, }) allowRunningInsecureContent Boolean //(可选) -允许一个 https 页面运行 http url 里的资源,包括 JavaScript, CSS 或 plugins. 默认值为 false.
跨平台兼容
原生相关
托盘
Tray
let tray = new Tray(`${__static}/menubar.png`)
const contextMenu = Menu.buildFromTemplate([
{label: 'Item1', type: 'radio', click() {dialog.showMessageBox({title: 'click', message: 'click the item', detail: 'The item has been clicked!'})}},
{label: 'Item2', type: 'radio'},
{label: 'Item3', type: 'radio', checked: true},
{label: 'Item4', type: 'radio'}
])
tray.setToolTip('This is an application.')
tray.setContextMenu(contextMenu)
应用菜单
Menu
MenuItem
let template = [
{label: 'item0', submenu: [{label: 'item0-0'}, {label: 'item0-1'}]},
{label: 'item1', submenu: [{label: 'item1-0'}, {label: 'item1-1'}]},
{label: 'item2', submenu: [{label: 'item2-0'}, {label: 'item2-1'}]},
{label: 'item3', submenu: [{label: 'item3-0'}, {label: 'item3-1'}]},
{label: 'item4', submenu: [{label: 'item4-0'}, {label: 'item4-1'}]}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
桌面通知
HTML5 Notification API
electron-notification
References
- Electron文档
- Electron-Vue