一、electron 安装以及创建、运行项目
1.在本地使用npm来全局安装electron
npm install -g electron
2.创建electron项目
创建目录(文件夹)
初始化npm包
mkdir electron-project-app
cd electron-project-app
npm init
初始化完成后,根目录下会出现一个json配置文件,即package.json,内容如下:
注意:npm init 选项 entry point 默认为 index.js,应该修改成应为 main.js,应用程序入口文件指向即main:main.js
{
"name": "electron-project-app",
"version": "1.0.0",
"description": "Hello World!",
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}
4.安装electron包
使用npm将electron 包安装到应用(项目)的开发依赖中
npm install --save-dev electron
在安装完成后,在package.json文件中会添加devDependencies关键词选项,从中可以看到electron的版本号
{
"devDependencies": {
"electron": "^25.2.0"
}
}
5.运行项目
在package.json配置文件中的scripts字段下增加一条start命令:
{
"name": "eletron-project-app",
"version": "1.0.0",
"description": "Hello World!",
"scripts": {
"start": "electron ."
},
"main": "main.js",
"author": "Jane Doe",
"license": "MIT"
}
然后运行如下命令,启动项目
npm start
在窗口命令(cmd、powershell)中会报错,因为没有找到主进程入口文件main.js,因此需要创建编写main.js
二、编写electron项目
大致步骤如下:
需要创建四个文件
- 在项目根目录创建一个主要入口文件main.js
- 在根目录创建index.html页面
- 在render目录下创建一个操作dom的render.js文件
- 为了通过预加载脚本从渲染器访问Node.js,在根目录即创建一个preload.js
关键词梳理:
- 主进程
- 应用程序生命周期
- 窗口管理
- 渲染器进程
- preload脚本(预加载脚本)
- 效率进程
1.创建主进程入口文件main.js
// electron 模块可以用来控制应用的生命周期和创建原生浏览窗口
const {app,BrowserWindow} = require('electron')
const path = require('path')
const createWindow = ()=>{
// 创建浏览窗口
const mainWindow = new BrowserWindow({
width:1200,
height:800,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// 加载index.html
mainWindow.loadFile('index.html')
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(()=>{
createWindow()
app.on("activate",()=>{
if(BrowserWindow.getAllWindows().length === 0){
createWindow()
}
})
})
// 当所有窗口都被关闭的时候退出程序
app.on('window-all-closed',()=>{
if(process.platform !== 'darwin'){
app.quit()
}
})
2.创建一个页面,在项目的根目录下创建一个index.html页面
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>electron</title>
</head>
<body>
<h2>欢迎来到electron应用程序</h2>
<p>electron renderer</p>
</body>
</html>
3.在项目的根目录下,创建preload.js文件:
注意:以后所有的业务逻辑都可以写在这个脚本中
// 所有的 Node.js API接口 都可以在 preload 进程中被调用.
// 它拥有与Chrome扩展一样的沙盒。
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])
}
})
再次运行命令:npm start
npm start
会弹出窗口,并且显示内容
三、视图界面快捷键操作
打开调试工具:
Ctrl + Shift + I
重新加载:
Ctrl + R
强制更新:
Ctrl + Shift + R
四、窗口示例 browserWindow
1、设置无边框窗口
要创建无边框窗口,需在main.js中将BrowserWindow的frame参数设置为 false:
{
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
width,:800,
height:600,
frame: false
})
}
官方文档说明:
默认情况下, 无边框窗口是不可拖拽的。 应用程序需要在 CSS 中指定 -webkit-app-region: drag 来告诉 Electron 哪些区域是可拖拽的(如操作系统的标准标题栏),在可拖拽区域内部使用 -webkit-app-region: no-drag 则可以将其中部分区域排除。 请注意, 当前只支持矩形形状
大致意思想要是在app任意地方点击拖住移动,需要把样式放在Body中,如下:
body{
-webkit-app-region: drag;
}
button {
-webkit-app-region: no-drag;
}
如果只想拖住标题栏(或者工具栏)区域移动就把样式放在相对应的css内容区域
header{
-webkit-app-region: drag;
}
button {
-webkit-app-region: no-drag;
}
2、任务栏
自定义任务栏功能实现:
- 窗口关闭
- 窗口最大化、切换恢复到默认大小
- 窗口最小化
在预加载脚本preload.js中触发事件,点击自定义的关闭按钮,将发送给主进程操作窗口从而实现功能
const { ipcRenderer } = require('electron')
// 窗口关闭
closeBtn.onclick = function(){
ipcRenderer.send('window-close')
}
// 窗口最大化、切换恢复到默认大小
maximizeBtn.onclick = function(){
ipcRenderer.send('window-maximize')
}
// 最小化窗口
miniimizeBtn.onclick = function(){
ipcRenderer.send('window-miniimize')
}
在主进程main.js中接收渲染进程发过来的
const { app,browserWindow,ipcMain } = require('electron')
const MainWindow= new browserWindow({
width:800,
height:600,
frame:false
})
// 窗口关闭
ipcMain.on('window-close',()=>{
MainWindow.close()
})
// 窗口最大化、切换恢复到默认大小
ipcMain.on('window-maximize',()=>{
if(MainWindow.isMaximized()){
MainWindow.restore()
}else{
MainWindow.maximize()
}
})
// 最小化窗口
ipcMain.on('window-minimize',()=>{
MainWindow.minimize()
})
3、底部托盘 tray
在main.js文件,app.whenReady方法中设置:
//创建托盘图标
const icon = nativeImage.createFromPath('./static/images/electron-logo.png')
// 初始化托盘
tray = new Tray(icon)
// 创建托盘菜单内容
const contextMenu = Menu.buildFromTemplate([
{ label: '设置', type: 'radio' },
{ label: '反馈意见', type: 'radio' },
{ label: '关于', type: 'radio', checked: true },
{ label: '退出', type: 'radio' }
])
tray.setContextMenu(contextMenu)
// 鼠标移动到托盘上显示的内容
tray.setToolTip('网易云音乐')
// 设置托盘标题
tray.setTitle('网易云音乐')
五、进程通信
六、应用程序开发API接口
1.Main process模块(主要进程模块)
- app
- autoUpdater
- browserWindow
- browserView
- contentTracing
- desktopCapturer 用来从桌面捕获音频和视频的媒体源的信息
- dialog 显示用于打开和保存文件、警报等的本机系统对话框
- globalShortcut 在应用程序没有键盘焦点时,监听键盘事件
- inAppPurchase Mac App Store中的应用内购买
- ipcMain 从主进程到渲染进程的异步通信
- Menu 菜单
- MessageChannelMain 主进程中用于通道消息传递的通道接口
- MessagePortMain 主进程中用于通道消息传递的端口接口
- nativeImage 使用 PNG 或 JPG 文件创建托盘、dock和应用程序图标
- nativeTheme 读取并响应Chromium本地色彩主题中的变化
- net 使用Chromium的原生网络库发出HTTP / HTTPS请求
- netLog 记录会话的网络事件
- Notification 创建OS(操作系统)桌面通知
- parentPort 与父进程通信接口
- powerMonitor 监视电源状态的改变
- powerSaveBlocker 阻止系统进入低功耗 (休眠) 模式
- process 处理对象的扩展
- protocol 注册自定义协议并拦截基于现有协议的请求
- pushNotifications 注册并接收远程推送通知服务的通知
- safeStorage 安全存储,允许访问简单的加密和解密字符串,以便存储在本地机器上
- screen 检索有关屏幕大小、显示器、光标位置等的信息
- session 管理浏览器会话、cookie、缓存、代理设置等
- ShareMenu 在 macOS 上创建共享菜单
- shell 使用默认应用程序管理文件和 url
- systemPreferences 获取system preferences
- TouchBar 触控板,为原生macOS应用创建TouchBar布局
- Tray 系统托盘,添加图标和上下文菜单到系统通知区
- utilityProcess 使用 Node.js 和 Message 端口创建了一个子进程
- webContents 渲染以及控制 web 页面,是 BrowserWindow 对象的一个属性
- webFrameMain 控制页面和内联框架(iframes),通常在导航事件中使用
app
app是主进程,控制应用程序的事件生命周期
app事件有:
- will-finish-launching
- ready
- will-finish-launching
- before-quit
- will-quit
- quit
macOS:
- open-file
- open-url
- activate
- did-become-active
- did-resign-active
- continue-activity
- will-continue-activity
- continue-activity-error
- activity-was-continued
- update-activity-state
- new-window-for-tab
- browser-window-blur
- browser-window-focus
- browser-window-created
- certificate-error
- select-client-certificate
- login
- gpu-info-update
- render-process-gone
- child-process-gone
app方法有:
app.quit()
app.exit()
app.relaunch()
app.isReady()
app.whenReady()
app.hide() // 隐藏所有的应用窗口,不是最小化
app.isHidden()
app.show() // 显示隐藏后的应用程序窗口。 不会使它们自动获得焦点
app.setAppLogsPath([path]) // 设置或创建一个您的应用程序日志目录,然后可以通过 app.getPath() 或 app.setPath(pathName, newPath) 进行操作
app.getAppPath() // 返回 string - 当前应用程序目录
app.getPath(name)
app.getFileIcon(path[, options])
app.setPath(name, path)
app.getVersion() // 加载应用程序的版本号
app.getName() // 获取当前应用程序的名称,即为该应用程序 package.json 文件的 name 字段
app.setName(name) // 设置当前应用程序的名字
app.getLocale()
app.getLocaleCountryCode() // 获取 用户操作系统区域设置的双字母 ISO 3166 国家代码
app.getSystemLocale()
app.getPreferredSystemLanguages()
app.addRecentDocument(path) // 将此 path 添加到最近打开的文件列表中
app.clearRecentDocuments() // 清空最近打开的文档列表
app.setAsDefaultProtocolClient(protocol[, path, args])
app.removeAsDefaultProtocolClient(protocol[, path, args])
app.isDefaultProtocolClient(protocol[, path, args])
app.getApplicationNameForProtocol(url)
app.getApplicationInfoForProtocol(url)
app.setUserTasks(tasks)
app.getJumpListSettings()
app.setJumpList(categories)
app.requestSingleInstanceLock([additionalData])
app.hasSingleInstanceLock()
app.releaseSingleInstanceLock()
app.setUserActivity(type, userInfo[, webpageURL])
app.getCurrentActivityType()
app.invalidateCurrentActivity() // 使当前的 Handoff 用户活动无效
app.resignCurrentActivity() // 将当前 Handoff 用户活动标记为非活动,但不使其失效
app.updateCurrentActivity(type, userInfo)
app.setAppUserModelId(id)
app.setActivationPolicy(policy)
app.importCertificate(options, callback)
app.configureHostResolver(options)
app.disableHardwareAcceleration() // 禁用当前应用程序的硬件加速
app.disableDomainBlockingFor3DAPIs()
app.getAppMetrics() // 返回 ProcessMetric[]: ProcessMetric 对象的数组,它统计了应用内所有进程的内存和 CPU 的使用情况
app.getGPUFeatureStatus() // 返回 GPUFeatureStatus - 来自 chrome://gpu/ 的图形特征状态
app.getGPUInfo(infoType)
app.enableSandbox() // 在应用程序上启用完全沙盒模式
app.setSecureKeyboardEntryEnabled(enabled) // 在应用中启用 Secure Keyboard Entry,通过使用此 API,可以防止密码和其他敏感信息等重要信息被其他进程截获
app属性有:
- app.accessibilitySupportEnabled
- app.applicationMenu
- app.badgeCount
- app.commandLine
- app.dock
- app.isPackaged // 对于大多数应用程序,此属性可用于区分开发和生产环境
- app.name 指明当前应用程序的名称
- app.userAgentFallback
- app.runningUnderRosettaTranslation
- app.runningUnderARM64Translation
const { app,browserWindow} = require('electron')
browserWindow
browserWindow是创建并控制浏览器窗口的
browserWindow参数:
- width 窗口的宽度
- hieght 窗口的高度
- x 窗口相对于屏幕左侧的偏移量
- y 窗口相对于屏幕左侧的偏移量
- useContentSize 窗口的实际尺寸将包括窗口边框的大小,稍微会大一点。 默认值为 false.
- center 窗口是否在屏幕居中
- movable 窗口是否可移动
- minimizable 窗口是否可最小化
- maximizable 窗口是否最大化
- closable 窗口是否可关闭
- focusable 窗口是否可以聚焦
- alwaysOnTop 窗口是否永远在别的窗口的上面
- fullscreen 窗口是否全屏
- fullscreenable 窗口是否可以进入全屏状态
- skipTaskbar 是否在任务栏中显示窗口
- titlestring 默认窗口标题 默认为"Electron"
- titleBarStyle 窗口标题栏样式(default 、hidden 、hiddenInset )
- icon 窗口图标
- show 窗口是否在创建时显示
- frame 设置为 false 时可以创建一个无边框窗口 默认值为 true
- parent 指定父窗口 默认值为 null
- modal 当前是否为模态窗口。 只有当窗口是子窗口时才起作用。 默认值为 false
- autoHideMenuBar 自动隐藏菜单栏,除非按了Alt键。 默认值为 false
- backgroundColor 窗口背景色
- transparent 使窗口 透明
- type 窗口的类型(linux:desktop、dock、toolbar、splash、notification)(mac:desktop,textured,panel)(window:toolbar)
- thickFrame
- webPreferences 网页功能设置
browserWindow事件有:
- page-title-updated // 文档更改标题时触发
- close
- closed
- session-end // 因为强制关机或机器重启或会话注销而导致窗口会话结束时触发
- unresponsive // 网页变得未响应时触发
- responsive // 未响应的页面变成响应时触发
const { browserWindow } = require('electron')
const win = new browserWindow({
width:800,
height:600,
})
// 加载网络(远程)url
win.loadUrl('https://www.xxxx.com/images/002.png')
// 加载本地html文件
win.loadFile('index.html')
- 父子窗口
- 模态窗口
2.Renderer process模块 (渲染进程模块)
- clipboard 在系统剪贴板上执行复制和粘贴操作
- contextBridge 在隔离的上下文中创建一个安全的、双向的、同步的桥梁
- crashReporter 将崩溃日志提交给远程服务器
- ipcRenderer 从渲染器进程到主进程的异步通信
- nativeImage 使用 PNG 或 JPG 文件创建托盘、dock和应用程序图标
- webFrame 自定义渲染当前网页
七、打包并且分发应用程序(打包、发布、更新)
使用electron-forge打包
1.将 Electron Forge 添加到您应用的开发依赖中,并使用其"import"命令设置 Forge 的脚手架:
npm install --save-dev @electron-forge/cli
npx electron-forge import
✔ Checking your system
✔ Initializing Git Repository
✔ Writing modified package.json file
✔ Installing dependencies
✔ Writing modified package.json file
✔ Fixing .gitignore
We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
Thanks for using "electron-forge"!!!
2.使用 Forge 的 make 命令来创建可分发的应用程序
npm run make
> my-electron-app@1.0.0 make /my-electron-app
> electron-forge make
✔ Checking your system
✔ Resolving Forge Config
We need to package your application before we can make it
✔ Preparing to Package Application for arch: x64
✔ Preparing native dependencies
✔ Packaging Application
Making for the following targets: zip
✔ Making for target: zip - On platform: darwin - For arch: x64