前言
Electron(以前称为Atom Shell)是一个开源框架,由GitHub开发,它允许开发者使用JavaScript、HTML和CSS等前端技术和Node.js后端环境来构建跨平台(Windows、Mac、Linux)的桌面应用程序。
一、Electron 定义
技术栈:Electron 结合了 Chromium 渲染引擎和 Node.js 运行时环境,使开发者能够在桌面应用中同时使用前端和后端技术。
跨平台:开发者只需编写一套代码,即可将其部署到多个操作系统上,无需为每个平台单独开发。
原生功能:通过主进程,Electron 提供了对操作系统原生功能的访问,如文件系统操作、窗口管理等。
Web 技术:Electron 的渲染进程使用标准的 Web 技术,这意味着开发者可以利用现有的 Web 开发技能和工
官网地址:https://www.electronjs.org/zh/docs/latest/
二、Electron 使用
1、新建项目、安装Electron
# 进入项目目录
cd myProject
# 初始化项目
npm init
以上命令执行完后,会自动生成package.json文件。需要填写author(作者) 与 description(描述) 的值。
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}
# 安装Electron
npm install --save-dev electron
在package.json中添加指令,用以运行Electron项目。
{
"scripts": {
"start": "electron ."
}
}
# 运行项目
npm run start
2、加载本地页面
加载本地页面需要两个Electron模块:app, BrowserWindow。
app 模块:它控制应用程序的事件生命周期。
BrowserWindow 模块:它创建和管理应用程序 窗口。
// main.js
// 引入Electron模块
const { app, BrowserWindow } = require('electron')
// 定义创建窗口的方法
const createWindow = () => {
const win = new BrowserWindow({
width: 800,//指定窗口宽度
height: 600,//指定窗口高度
autoHideMenuBar:true//隐藏默认菜单
})
win.loadFile('./index.html')
}
app.on('ready',()=>{
// 在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口。
createWindow();
})
关闭所有窗口时退出应用 (Windows & Linux)
app.on('window-all-closed', () => {
// 如果用户不是在 macOS(darwin) 上运行程序,则调用 app.quit()。
if (process.platform !== 'darwin') app.quit()
})
如果没有窗口打开则打开一个窗口 (macOS)
当 Linux 和 Windows 应用在没有窗口打开时退出了,macOS 应用通常即使在没有打开任何窗口的情况下也继续运行,并且在没有窗口可用的情况下激活应用时会打开新的窗口。
为了实现这一特性,监听 app 模块的 activate 事件。如果没有任何浏览器窗口是打开的,则调用 createWindow() 方法。
app.on('ready',()=>{
createWindow();
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
3、主进程与渲染进程
主进程:每个Electron应用都有一个主进程,它是启动时执行的脚本文件。主进程负责管理原生元素如菜单栏、窗口等。主进程使用Node.js环境,因此可以直接访问操作系统API。
渲染进程:每个窗口(BrowserWindow)对应一个渲染进程。渲染进程负责加载网页并执行其中的Web技术代码。每个渲染进程都是独立的,相互之间不会影响。
4、Preload(预加载)脚本
预加载脚本(Preload Script)是 Electron 中的一个重要概念,用于在渲染进程中提供额外的功能和安全控制。预加载脚本在渲染进程加载之前执行,允许开发者在渲染进程中注入自定义的全局变量、函数或模块,从而扩展渲染进程的能力。
1、创建预加载脚本
// 引入contextBridge和ipcRenderer
const { contextBridge, ipcRenderer } = require('electron');
// 使用 contextBridge 模块安全地暴露全局变量和函数
contextBridge.exposeInMainWorld('api', {
sayHello: () => {
return "Hello from Preload Script!";
},
sendToMain: (message) => {
ipcRenderer.send('message-to-main', message);
},
receiveFromMain: (callback) => {
ipcRenderer.on('message-from-main', (event, message) => callback(message));
}
});
2、修改主进程
//引入ipcMain
const { app, BrowserWindow, ipcMain } = require('electron');
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: __dirname + '/preload.js', // 指定预加载脚本
}
});
win.loadFile('index.html');
}
// 监听从渲染进程发送的消息
ipcMain.on('message-to-main', (event, message) => {
console.log('Message received from renderer:', message);
});
修改渲染进程
// 发送消息到主进程
api.sendToMain('Hello from Renderer!');
// 接收主进程的消息
api.receiveFromMain((message) => {
console.log(message);
});
5、进程通信
1、渲染进程向主进程单向通信
ipcRenderer.send()与ipcMain.on()
1、主进程
ipcMain.on('message-to-main', (event, message) => {
console.log('Message received from renderer:', message);
});
2、预加载脚本
contextBridge.exposeInMainWorld('api', {
sendToMain: (message) => {
ipcRenderer.send('message-to-main', message);
}
});
3、渲染教程
// 发送消息到主进程
api.sendToMain('Hello from Renderer!');
2、渲染进程、主进程双向通信
ipcRenderer.invoke与ipcMain.handle
1、主进程
// src/main.js/app.on('ready'){
ipcMain.handle('getMainData', handleFileOpen)
//src/mian.js
async function handleFileOpen () {
return '主进程数据'
}
2、预加载脚本
contextBridge.exposeInMainWorld('api', {
invokeToMain: () => {
ipcRenderer.invoke('getMainData')
}
});
3、渲染教程
const filePath = await window.api.invokeToMain()
3、主进程向渲染进程通信
与渲染进程向主进程通信一致。只是方向不同
4、思考渲染进程之间的通信
通过主进程中转。
6、打包
1、安装打包工具
npm install --save-dev electron-builder
2、构建命令
"scripts": {
"start": "electron .",
"build": "electron-builder"
}
3、配置方式一:package.json
{
"name": "your-app-name",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder"
},
"build": {
"appId": "com.yourcompany.yourapp",
"productName": "YourAppName",
"copyright": "Copyright © 2024 Your Company",
"directories": {
"output": "dist"
},
"files": [
"**/*",
"!**/*.ts",
"!**/*.map",
"!**/*.spec.js"
],
"nsis": {
"oneClick": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"installerIcon": "./build/icon.ico",
"uninstallerIcon": "./build/icon.ico",
"installerHeaderIcon": "./build/icon.ico",
"createDesktopShortcut": true,
"createStartMenuShortcut": true
},
"mac": {
"icon": "./build/icon.icns",
"category": "public.app-category.developer-tools"
},
"dmg": {
"background": "./build/background.png",
"icon": "./build/icon.icns",
"window": {
"width": 600,
"height": 400
}
},
"linux": {
"target": ["deb", "rpm"],
"icon": "./build/icon.png"
},
"win": {
"target": ["nsis"],
"icon": "./build/icon.ico"
}
},
"dependencies": {
"electron": "^23.0.0"
},
"devDependencies": {
"electron-builder": "^22.14.13"
}
}
4、配置方式二:builder.config.js
module.exports = {
appId: 'com.yourcompany.yourapp',
productName: 'YourAppName',
copyright: 'Copyright © 2024 Your Company',
directories: {
output: 'dist'
},
files: [
'**/*',
'!**/*.ts',
'!**/*.map',
'!**/*.spec.js'
],
nsis: {
oneClick: false,
allowElevation: true,
allowToChangeInstallationDirectory: true,
installerIcon: './build/icon.ico',
uninstallerIcon: './build/icon.ico',
installerHeaderIcon: './build/icon.ico',
createDesktopShortcut: true,
createStartMenuShortcut: true
},
mac: {
icon: './build/icon.icns',
category: 'public.app-category.developer-tools'
},
dmg: {
background: './build/background.png',
icon: './build/icon.icns',
window: {
width: 600,
height: 400
}
},
linux: {
target: ['deb', 'rpm'],
icon: './build/icon.png'
},
win: {
target: ['nsis'],
icon: './build/icon.ico'
}
};
5、配置项解释
appId: 应用程序的唯一标识符。
productName: 应用程序的名称。
copyright: 版权信息。
directories.output: 输出目录。
files: 包括和排除的文件模式。
nsis: NSIS 安装程序的配置。
mac: macOS 应用程序包的配置。
dmg: macOS DMG 镜像的配置。
linux: Linux 包的配置。
win: Windows 安装程序的配置。
asar: 是否将应用程序打包为 ASAR 归档文件。
publish: 自动发布构建到 GitHub、BinTray 等。
squirrelWindows: Squirrel.Windows 安装程序的配置。
mac.notarize: macOS 应用程序的公证配置。
结语
编程是一场思维的马拉松,而不是短跑。相信大家都听过一句话,“种一棵树最好的时间是十年前,其次是现在”,望与诸君共勉。