本文主要讲以下几点
打开官网第一眼就是使用 JavaScript, HTML 和 CSS 构建跨平台的桌面应用
,更加通俗一点就是一个桌面浏览器,实际上这样理解也是对的。因为electron就是通过javaScript使chromium来展示web页面
electron产品我使用过表现优秀
我认为以下是快速开始的最好办法
直接使用electron官方提供的例子
// 看这个的源码,很简单可以快速上手
# 克隆这仓库
$ git clone https://github.com/electron/electron-quick-start
# 进入仓库
$ cd electron-quick-start
# 安装依赖库
$ npm install
# 运行应用
$ npm start
如果想了解这个electron的API可以克隆这个库并运行
git clone https://github.com/electron/electron-api-demos
cd electron-api-demos
npm install
npm start
渲染进程调试(web页面)
渲染器进程这chrome浏览器一样,BrowserWindow创建窗口后添加窗口实例.webContents.open
主进程Electron调试
使用vsCode中的debug,注意调试路径,如果需要增加变量环境依照配置增加即可
主要聊electron中主进程的生命周期,渲染器的部分生命周期,一般只介绍通用都存在的,如果只有某个系统有的api就不写在这里了,大家可以自行查阅
正常流程会触发的生命周期
will-finish-launching
:当应用程序完成基础的启动的时候被触发web-contents-created
:webContents被创建完成browser-window-created
:BrowserWindow被创建完成ready
:当 Electron 完成初始化时被触发remote-require
: 引入remote时被调用before-quit
: 在应用程序开始关闭窗口之前触发will-quit
:当所有窗口都已关闭并且应用程序将退出时发出quit
: 在应用程序退出时发出window-all-closed
:当所有的窗口都被关闭时触发这里要注意如果是进程杀死退出的所有都不触发,如果是cmd+Q
或者开发者使用app.quit()
退出的window-all-closed
是不会被触发的,基本操作一般在ready中处理
进程相关
gpu-process-crashed
: 当 gpu 进程崩溃或被杀时触发。其他
browser-window-focus
: 在 browserWindow 获得焦点时发出browser-window-blur
:在 browserWindow 失去焦点时发出ready-to-show
:当页面已经渲染完成(但是还没有显示) 并且窗口可以被显示时触发move
: 窗口移动resize
: 调整窗口大小后触发close
: 在窗口要关闭的时候触发。 它在DOM 的beforeunload 和 unload 事件之前触发.blur
: 失去焦点,同appfocus
: 获得焦点,同appmaximize
:窗口最大化时触发unmaximize
: 当窗口最大化退出状态触发minimize
: 窗口最小化时触发restore
: 当窗口从最小化还原触发did-finish-load
:导航完成时触发,即选项卡的旋转器将停止旋转,并指派onload事件后did-finish-load
: 这个事件类似于 did-finish-load, 不过是在加载失败或取消后触发dom-ready
: 一个框架中的文本加载完成后触发该事件crashed
: 当渲染进程崩溃或被结束时触发unresponsive
: 页面未响应触发devtools-opened
: 当开发者工具被打开时,触发该事件。devtools-closed
: 当开发者工具被关闭时,触发该事件。chrome浏览器由于每个标签页都是一个进程,而electron所运行的进程称为主进程并且只有一个,主进程要操控浏览器的每个标签的网页称为渲染器进程,如何通讯呢?
进程
进程是正在运行的程序的实例(狭义定义)
electron中的主进程
Electron 运行 package.json 的 main 脚本的进程被称为主进程。 在主进程中运行的脚本通过创建web页面来展示用户界面。 一个 Electron 应用总是有且只有一个主进程。
electron中的渲染器进程
由于 Electron 使用了 Chromium 来展示 web 页面,所以 Chromium 的多进程架构也被使用到。 每个 Electron 中的 web 页面运行在它自己的渲染进程中。
渲染器进程与主进程之间的区别
主进程使用 BrowserWindow 实例创建页面。 每个 BrowserWindow 实例都在自己的渲染进程里运行页面。 当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。
主进程管理所有的web页面和它们对应的渲染进程。 每个渲染进程都是独立的,它只关心它所运行的 web 页面。
在页面中调用与 GUI 相关的原生 API 是不被允许的,因为在 web 页面里操作原生的 GUI 资源是非常危险的,而且容易造成资源泄露。 如果你想在 web 页面里使用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。
主进程与渲染器进程通过ipcMain与ipcRenderer来通讯
主进程向渲染器进程通讯
这个方式主要是主进程中使用ipcMain使用on监听,监听获取后通过event.sender
(相当于webContent)send
来发送一个事件,渲染进程中使用ipcRenderer通过on来接收,如果是同步可以通过evnet.returnValue
来返回主进程的结果代码如下:
渲染器进程向主进程通讯
渲染器进程主要通过ipcRenderer这个模块中的send来发送,该方法中可以同步与异步发送消息,接收消息使用on来接收
常用方式:
electron-builder 是一个完整的解决方案,并且自带自动更新策略
electron-builder打包在package的script配置好
"build": {
"appId": "your.id", // appid
"productName": "程序名称", // 程序名称
"files": [ // 打包需要的不过滤的文件
"build/**/*",
"main.js",
"node_modules/**/*"
],
"directories": {
"output": "./dist-out", // 打包输出的目录
"app": "./", // package所在路径
"buildResources": "assets"
},
"nsis": {
"oneClick": false, // 是否需要点击安装,自动更新需要关掉
"allowToChangeInstallationDirectory": true, //是否能够选择安装路径
"perMachine": true // 是否需要辅助安装页面
},
"win": {
"target": [
{
"target": "nsis", // 输出目录的方式
"arch": [ // 输出的配置ia32或者x64/x86
"x64"
]
}
],
"publish": [ // 自动更新的配置
{
"provider": "generic", // 自己配置更新的服务器要选generic
"url": "http://127.0.0.1:8080/updata/" //更新配置的路径
}
]
}
}
在package.json中增加的快速启动项
"scripts": {
"pack": "electron-builder --dir",
"dist": "electron-builder"
}
启动打包
通常需要注意的点
path.join()
来处理一下。The process cannot access the file because it is being used by another process.
这个问题多数是vscode占用了关掉重开就好了如果配合create-react-app创建出来的应用
electron.js
找不到的警告,并且在上面提示让你去看网页中的方法,可以通过electron-builder提示的网址来修改,这实际是一个教程需要科学上网。如果在API中看到autoUpdater这个API,希望在看到这个API之前先参考官方的自动更新这样会让你少点坑,因为electron-builder的自动更新机制和electron提供有些不一样,electron-builder官网也有说明,否则就会一直报error了
这个更新实际上是对比例两个版本之间的版本号,如果当前版本小于,服务器版本的话就会进行下载更新
更新机制
autoUpader生命周期
error
: 如果任意一个环节有问题就会走到这步checking-for-update
:当开始检查更新的时候触发。update-available
: 发现更新update-not-available
:当没有可用更新的时候触发.update-downloaded
: 在更新下载完成的时候触发。before-quit-for-update
: 此事件是在用户调用quitAndInstall()之后发出的。更新要注意的点:
electron-updater
这个模块,非原生模块net::ERR_CONNECTION_REFUSED
autoUpdater
的流程需要一个dev-app-update.yml
的文件放在与main.js
同一层级的地方,类似win-ia32-unpacked/resource/app-update.yml
这样的文件,直接复制改名就能使用autoUpdater.quitAndInstall()
did-finish-load
这个声明周期,在这里面做处理,根据场景可以使用once
来监听http-server -o
,如果没有就全局安装一个npm i http-server -g
,在package中需要配置publish
中的 "provider": "generic"
spawn **/*.exe ENOENT
这类的可能是你在开发环境运行了一个未安装的应用,并且使用了autoUpdater.quitAndInstall()
就会报错,如果是安装好了就不会报这个错//electron-quick-start
//main.js 主进程中
// 可以没有这个
const { autoUpdater } = require('electron-updater')
// ================= start 非必须 ===============
const log = require('electron-log');
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';
// ================ end 非必须 ==================
// 封装
function sendStatusToWindow(text) {
log.info(text);
mainWindow.webContents.send('message', text);
}
/**
* 自动更新
*/
function checkUpdata() {
autoUpdater.setFeedURL('http://127.0.0.1:8080/updata/')
// autoUpdater.on('error', (error) => {
// sendStatusToWindow( `[error]:${error}`)
// })
autoUpdater.on('checking-for-update', () => {
sendStatusToWindow('Checking for update...');
// mainWindow.webContents.send('downlaod')
})
autoUpdater.on('update-available', (info) => {
sendStatusToWindow('Update available.');
})
autoUpdater.on('update-not-available', (info) => {
sendStatusToWindow('Update not available.');
})
autoUpdater.on('error', (err) => {
sendStatusToWindow('Error in auto-updater. ' + err);
})
autoUpdater.on('download-progress', (progressObj) => {
let log_message = "Download speed: " + progressObj.bytesPerSecond;
log_message = log_message + ' - Downloaded ' + progressObj.percent + '%';
log_message = log_message + ' (' + progressObj.transferred + "/" + progressObj.total + ')';
sendStatusToWindow(log_message);
mainWindow.webContents.send('downloadExe', progressObj.percent)
})
autoUpdater.on('update-downloaded', (info) => {
mainWindow.webContents.send('downloaded')
sendStatusToWindow('Update downloaded');
// autoUpdater.quitAndInstall();
});
如果是windows环境需要准备 vs2015 与python2.7的环境
vs2015 以下方式可选其一
npm install --vs2015 -g windows-build-tools
(推荐)程序中可添加的本地数据库,最多使用的两款
为自己的数据加上本地数据库sqlite3
sqlite3【gitHub】
为程序添加sqlite3npm i sqlite3
或者yarn add sqlite3
如何使用?
// 官网例子
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:'); // 这里是把数据存入内存
db.serialize(function() {
var db = new sqlite3.Database()
db.run("CREATE TABLE lorem (info TEXT)");
var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
for (var i = 0; i < 10; i++) {
stmt.run("Ipsum " + i);
}
stmt.finalize();
db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
console.log(row.id + ": " + row.info);
});
});
db.close();
sqilte3在安装的时候自动生成sqlite所需要的文件包,这个二进制文件需要使用node-pre-gyp
或者是node-gyp
这也就是为什么需要安装环境的原因,在这一步鬼知道当时报了多少东西,尤其是还要把这玩意弄进内网。
比如说:
开始运行的时候就报Error: Cannot find module 'E:\electronjs\electron-quick-start\node_modules\sqlite3\lib\binding\electron-v4.0-win32-x64\node_sqlite3.node'
类似这样的东西,实际上确实没有这个东西,怎么解决呢?
node-gyp
这个模块直接重新编译一个版本正确的node-gyp rebuild
--target=4.0.4 --arch=x64
--target_platform=win32 --dist-url=https://atom.io/download/electron/
--module_name=node_sqlite3 --module_path=../lib/binding/electron-v4.0-win32-x64
// 使用到的模块解析
// target => electron的版本号一定要一直
// target_platform => 需要打包的平台ia32/x64等
// dist-url => 这个是需要下载相关内容的地址
// module_name => 需要打包的模块名称
// module_path => 打包输出的地方
如果觉得麻烦可以试试npm i electron-rebuild -D
然后在使用./node_modules/.bin/electron-rebuild
重新编译一遍,有时候可能是缓存问题,把缓存清除npm cache clear -f
清除一下,还有就是npm i
重新安装一下,因为环境的问题会跳出各种问题,可以多多尝试这些方法
was compiled against a different Node.js version using
NODE_MODULE_VERSION 64. This version of Node.js requires
NODE_MODULE_VERSION 69. Please try re-compiling or re-installing
如让你选择node编译版本的github【issues】====>也有可能是编译问题,利用electron-rebuild 重新编译一遍或者把sqlite3降级
需要注意的
error MSB4019: 未找到导入的项目Microsoft.WebApplication.targets
重新安装一下vs2015工具包,或者以前安装的有问题重新安装(我就碰到了)binding.gyp
这个python文件以及其他配置所以直接进入node_modules\sqlite3
这个文件运行 node-gyp的操作electron-vue
发现可以使用app.getPath('userData')
这个方法进行获取app可缓存地址,然后使用path.join
合并一下路径就解决了无法生成DB文件的问题,事实上indexDB,locaStore这个两个的存储文件也在这个目录下globalShortcut
: 注册全局快捷键Tray
: 托盘Menu
:菜单事件内网开发真的很烦。。
首先需要环境,然后就是需要下载的包,其次就是需要编译后的各种文件如sqlite3编译后的文件等如果在内网开发electron就需要把这些需要的包全都复制到对应位置
大部分需要配置的文件都在C:\Users\xxx
xxx代表你所在的文件夹,
部分下载缓存文件在C:\Users\xxx\AppData\Local
目录下的electron 和 electron-builderer里
以下文章大部分阅读过,觉得不错推荐给大家