是什么
Electron 使用 JavaScript,HTML 和 CSS,来构建跨平台的桌面应用程序。
讲什么
- 安装
- 创建一个应用程序
- 主进程
- 渲染进程
- 主进程 send 渲染进程
- 渲染进程 send 主进程
- 渲染进程 send 渲染进程
- 原生菜单操作
- 文件读写
- 打包部署
安装
npm install electron --S
创建一个应用程序
demo/
├── package.json
├── main.js
└── index.html
- main.js
const {app, BrowserWindow} = require('electron')
const iconPath = path.join(__dirname, './src/img/icon.png') //应用运行时的标题栏图标
let win
app.on('ready', function createWindow () {
// 可以创建多个渲染进程
win = new BrowserWindow({
width: 800,
height: 600,
frame: false, // 创建无边框窗口
resizable: false, //不允许用户改变窗口大小
icon: iconPath, //应用运行时的标题栏图标
fullscreen: true, // 默认全屏显示
webPreferences:{
backgroundThrottling: false, //设置应用在后台正常运行
nodeIntegration:true, //设置能在页面使用nodejs的API
contextIsolation: false,
preload: path.join(__dirname, './preload.js') // 预加载
}
})
win.removeMenu() // 去掉菜单栏
win.show()
// 渲染进程中的web页面可以加载本地文件
win.loadFile('index.html')
// 在页面被关闭后清除该变量,防止内存泄漏
win.on('closed', function () {
win = null
})
})
// 页面全部关闭后关闭主进程,不同平台可能有不同的处理方式
app.on('window-all-closed', () => {
app.quit()
})
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo</title>
</head>
<body>
<div>一个electron项目</div>
<script>
</script>
</body>
</html>
主进程
任何 Electron 应用程序的入口都是 main 文件。 这个文件控制了主进程,它运行在一个完整的Node.js环境中,负责控制您应用的生命周期,显示原生界面,执行特殊操作并管理渲染器进程
- 运行package.json中的main脚本的进程是主进程。
- 一个electron应用有且只有一个主进程。
- 主进程可以进行GUI相关的原生API操作。
渲染进程
每个web页面运行的环境就是渲染进程
- 使用BrowserWindow类开启一个渲染进程并将这个实例运行在该进程中
- 当一个BrowserWindow实例被销毁后,相应的渲染进程也会被终止。
- 渲染进程中不能调用原生资源,但是渲染进程中同样包含Node.js环境,所以可以引入Node.js 模块, 通过 ** webPreferences: { nodeIntegration: true, } **
主进程 send 渲染进程
- 主进程 main.js
// 主进程向渲染进程发送消息
win.webContents.on('onload', () => {
win.webContents.send('msg', '消息来自主进程')
})
- 渲染进程 index.html
const {ipcRenderer} = require('electron')
ipcRenderer.on('msg', (event, message) => {
console.log(message) // 消息来自主进程
})
渲染进程 send 主进程
- 主进程 main.js
const {ipcMain} = require('electron')
ipcMain.on('indexMsg',(event,msg) => {
console.log(msg) //消息来自渲染进程
})
- 渲染进程 index.html
const {ipcRenderer} = require('electron')
ipcRenderer.send('indexMsg','消息来自渲染进程')
渲染进程 send 渲染进程
- 使用全局共享属性
//主进程
global.config = {
user: ''
}
//渲染进程一
const {remote} = require('electron')
remote.getGlobal('config').user = 'wxh'
//渲染进程二
const {remote} = require('electron')
console.log(remote.getGlobal('config').user) //wxh
- 利用主进程做消息中转站
//渲染进程1
ipcRenderer.send('connect', '来自渲染进程1的消息')
//主进程
ipcMain.on('connect', (event, message) => {
win.webContents.send('sendTo', message);
}
//渲染进程2
ipcRenderer.on('sendTo', (event, message) => {
console.log(message) //来自渲染进程1的消息
}
)
原生菜单操作
菜单的参数说明:
当设置了 frame: false, 的时候,无边框窗口是不可拖拽的。应用程序需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖拽的。
// 整个窗口都可拖拽,
html,body {
height: 100%;
width: 100%;
}
body{
-webkit-app-region: drag;
}
关闭窗口
win.on('closed', () => { win = null })
系统托盘
程序启动时,将应用程序加入系统托盘。在Electron中,借助Tray模块实现。
const { app, BrowserWindow, Tray, Menu } = electron
const iconPath = path.join(__dirname, './src/img/icon.png')
let win, tray
app.on('ready', () => {
// ...
tray = new Tray(iconPath) //实例化一个tray对象
tray.setToolTip('hello exe') //鼠标移到托盘中应用程序的图标上时,显示的文本
tray.on('click', () => { //点击图标的响应事件,这里是切换主窗口的显示和隐藏
if(win.isVisible()){
win.hide()
}else{
win.show()
}
})
tray.on('right-click', () => { //右键点击图标时,出现的菜单,通过Menu.buildFromTemplate定制,这里只包含退出程序的选项。
const menuConfig = Menu.buildFromTemplate([
{
label: 'Quit',
click: () => app.quit()
}
])
tray.popUpContextMenu(menuConfig)
})
})
窗口位置设置
const { app, BrowserWindow, Tray, Menu } = electron
function createRemindWindow (task) {
//创建提醒窗口
remindWindow = new BrowserWindow({
//...options
})
//获取屏幕尺寸
const size = screen.getPrimaryDisplay().workAreaSize
//获取托盘位置的y坐标(windows在右下角,Mac在右上角)
const { y } = tray.getBounds()
//获取窗口的宽高
const { height, width } = remindWindow.getBounds()
//计算窗口的y坐标
const yPosition = process.platform === 'darwin' ? y : y - height
//setBounds设置窗口的位置
remindWindow.setBounds({
x: size.width - width, //x坐标为屏幕宽度 - 窗口宽度
y: yPosition,
height,
width
})
//当有多个应用时,提醒窗口始终处于最上层
remindWindow.setAlwaysOnTop(true)
remindWindow.loadURL(`file://${__dirname}/src/index.html`)
}
文件读写
Electron读写本地文件其实和nodeJs差不多,只是中间加了一层API
- 主进程 main.js
import { app, BrowserWindow, Menu,ipcMain } from 'electron';
ipcMain.on('asynchronous-file', function(event, arg) {
// arg是从渲染进程返回来的数据
console.log(arg);
// fs.writeFile(path.join(__dirname, "../renderer/data/student.json"),JSON.stringify(arg), "utf8",(err)=>{});
fs.readFile(path.join(__dirname,"../renderer/data/student.json"),"utf8",(err,data)=>{
if(err){
event.sender.send('asynchronous-reply', "读取失败");
}else{
event.sender.send('asynchronous-reply', data);
}
})
});
- 渲染进程 index.js
// 渲染进程
const ipcRenderer = require("electron").ipcRenderer;
ipcRenderer.on("asynchronous-reply", function(event, arg) {
// 这里的arg是从主线程请求的数据
console.log("render+" + arg);
});
// 这里的会传递回给主进程,这里的第一个参数需要对应着主进程里on注册事件的名字一致
ipcRenderer.send("asynchronous-file", "传递回去值");
打包部署
- electron-packager
我们可以利用 electron-packager把我们现有的electron应用打包为exe可执行文件。
npm install electron-packager --save-dev
配置 package.json
// package.json
"scripts": {
"win32": "electron-packager ./ appDemo --platform=win32 --arch=ia32 --out=./app --app-version=1.0.0 --overwrite --icon=./favicon.ico",
"win64": "electron-packager ./ appDemo --platform=win32 --arch=x64 --out=./app --app-version=1.0.0 --overwrite --icon=./favicon.ico"
}
- electron-builder
electron-builder不仅可以打包为exe可执行文件,还可以打包为可安装程序。
yarn add electron-builder --dev
配置 package.json
"scripts": {
"pack": "electron-builder --dir",
"dist": "electron-builder"
},
"build": {
"productName": "appDemo", // app中文名称
"appId": "appDemoId",// app标识
"directories": { // 打包后输出的文件夹
"buildResources": "resources",
"output": "dist/"
}
"files": [ // 打包后依然保留的源文件
"dist/electron",
"node_modules/",
"package.json"
],
"mac": { // mac打包配置
"target": "dmg",
"icon": "icon.ico"
},
"win": { // windows打包配置
"target": "nsis",
"icon": "icon.ico"
},
"dmg": { // dmg文件打包配置
"artifactName": "appDemo.dmg",
"contents": [
{
"type": "link",
"path": "/Applications",
"x": 410,
"y": 150
},
{
"type": "file",
"x": 130,
"y": 150
}
]
},
"nsis": { // nsis文件打包配置
"oneClick": false,
"allowToChangeInstallationDirectory": true, // 允许修改安装目录
"allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
"installerIcon": "./build/icons/aaa.ico",// 安装图标
"uninstallerIcon": "./build/icons/bbb.ico",//卸载图标
"installerHeaderIcon": "./build/icons/aaa.ico", // 安装时头部图标
"createDesktopShortcut": true, // 创建桌面图标
"createStartMenuShortcut": true,// 创建开始菜单图标
"shortcutName": "xxxx", // 图标名称
"include": "build/script/installer.nsh", //包含的自定义nsis脚本这个对于构建需求严格得安装过程相当有用。
},
}
参考
- www.electronjs.org/docs/tutori…
- electron-react-boilerplate:electron + react: github.com/electron-re…
- electron-vue: electron + vue : github.com/SimulatedGR…