概述
Electron
是由Github
开发,用HTML
,CSS
和JavaScript
来构建跨平台桌面应用程序的一个开源库。 Electron
通过将Chromium
和Node.js
合并到同一个运行时环境中,并将其打包为Mac
,Windows
和Linux
系统下的应用来实现这一目的。Electron
运行package.json
的 main
脚本的进程被称为主进程,在主进程中可以通过创建BrowserWindow
来展示用户界面,Electron
只有一个主进程,每个运行在Chromium
中的Web页面是独立的渲染进程。Electron
可与操作系统做底层交互。在渲染进程中调用GUI原生API是不被允许的,如果要调用这些API,要与主进程通信,在主进程中处理。在Electron
中,有些API针对主进程,有些则针对渲染进程,具体请查看文档。Electron
通过remote模块暴露一些通常只能在主进程中获取到的API。 为了在渲染进程中创建一个BrowserWindow
的实例,我们通常使用remote模块为中间件。在Electron
的主进程和渲染进程中,都可以调用nodeJS

它可以用来干嘛
以下业务场景下,您可以考虑使用Electron
:
瘦客户端,跨平台,需支持Windows,Linux和Mac的客户端程序;
小程序、脚本类开发工具,比如目前市面上的支付宝小程序和头条小程序,使用的都是
Electron
,而微信小程序开发工具使用的nw.js
;基于Web的刷分工具;
其他;
优势和比较
体积适中,比CEF小很多,运行速度快,能与底层操作系统交互,扩展原生接口方便,跨平台,不支持XP,必须是Windows 7或以上,成功案例多,如Slack,Visual Studio
Code,Atom等。支持NodeJS,入手容易,与nw.js相比,Electron发展更快,bug更少,贡献者更多,社区更活跃。
常见问题
主进程的常用API
在渲染进程中可以判断在线离线情况:
navigator.onLine
,如果要在主进程中处理,可以通过渲染进程向主进程发送消息。主进程中可以通过
win.setProgressBar(0.5)
设置任务栏图标的进度;BrowserWindow
类控制浏览器行为,方法比较常用,比如setSize用来重置窗口大小(登录=》主窗口),具体api详见:https://electronjs.org/docs/api/browser-window可以在主进程或渲染进程中调用剪贴板操作:
const { clipboard } = require('electron');
clipboard.writeText('string');//writeHTML,writeImage,writeRTF,writeBookmark,write
clipboard.readText('selection'); //readHTML,readImage,readRTF,readBookmark()
可以在主线程中查看cookies:
session.defaultSession.cookies.get({ url: 'http://www.github.com' }, (error, cookies) => {
console.log(error, cookies)
})
可以在主线程中调用系统对话框,比如文件保存对话框,文件打开对话框等,如果要在渲染进程中打开,请使用remote;
可以在主线程中注册快捷键:
const { app, globalShortcut } = require('electron')
app.on('ready', () => {
const ret = globalShortcut.register('CommandOrControl+X', () => {
console.log('CommandOrControl+X is pressed')
})
if (!ret) {
console.log('registration failed')
}
console.log(globalShortcut.isRegistered('CommandOrControl+X'))
})
app.on('will-quit', () => {
globalShortcut.unregister('CommandOrControl+X')
globalShortcut.unregisterAll()
})
菜单只允许在主线程中通过
new Menu()
创建,要在渲染进程中创建菜单,请使用remote
,如下:
<!-- index.html -->
<script>
const { remote } = require('electron')
const { Menu, MenuItem } = remote
const menu = new Menu()
menu.append(new MenuItem({ label: 'MenuItem1', click() { console.log('item 1 clicked') } }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }))
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup({ window: remote.getCurrentWindow() })
}, false)
</script>
remote
模块为渲染进程和主进程通信提供一种简单方法,如:const { BrowserWindow } = require('electron').remote
,以上BrowserWindow
是远程对象。它还有其他常见的方法,如:返回当前网页窗口getCurrentWindow()
,返回当前网页内容:getCurrentWebContents()
,获取全局变量getGlobal()
,主进程中的process
对象等。
利用remote在渲染进程中调用主进程API
//这样写在渲染进程中时行得通的,但是在主进程中是'未定义'
const { remote } = require('electron')
const { BrowserWindow } = remote
const win = new BrowserWindow()
网络处理:http和websocket
在渲染进程中,可以通过http模块处理网络请求:
const http = require('http');
var _param = JSON.stringify({
script:encodeURIComponent(_script)
});
const request = http.request({
method:"POST",
host:'localhost',
port:8080,
path:'/spider/base/previewScript',
headers:{
'Content-Type': 'application/json',
'Content-Length': _param.length,
'token':'xxx'
}
},(res) => {
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
})
res.on('end', () => {
console.log('No more data in response.')
})
});
request.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
request.write(_param);
request.end();
具体http的详细API可参考:https://nodejs.org/dist/latest-v4.x/docs/api/http.html#http_http_get_options_callback
也可以使用进程间通讯,将渲染进程中的ajax请求发往主进程
ClientRequest
,主进程执行后利用回调函数到渲染进程,这种是官方推荐用法。详见:https://electronjs.org/docs/api/client-request
至于WebSocket,可以使用SockJS
+Stomp
,如下:
var sock = new SockJS("http://localhost:8080/websocket-spider?token=xxx");
var stompClient = Stomp.over(sock);
var headers = {
a:"1"
};
stompClient.connect(headers,(frame) => {
stompClient.subscribe('频道名', (msg) => {
......
});
}, (err) => {
// 连接发生错误时的处理函数
console.log(err);
});
});
主进程和渲染进程通信
渲染进程可以向主进程发送消息,以便让主进程调用相应的API,在渲染进程中:
//发送同步消息到主进程
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong"
//接收渲染进程向主进程发送异步消息的回调
ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
})
//发送异步消息到主进程
ipcRenderer.send('asynchronous-message', 'ping')
在主进程中:
//接收来自渲染进程的异步消息
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.sender.send('asynchronous-reply', 'pong')
})
//接收来自渲染进程的同步消息
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
})
收集程序的崩溃报告
收集日志的服务端可以由socorro
或mini-breakpad-server
构建,客户端代码如下:
const { crashReporter } = require('electron')
crashReporter.start({
productName: 'YourName',
companyName: 'YourCompany',
submitURL: 'https://your-domain.com/url-to-submit',
uploadToServer: true
})
你可以继续阅读:
一款自动生成后台代码的管理系统的设计与实现 | “大”中台,“小”前端的架构演变| 云服务平台中推送服务的设计与实现 | 对微服务的理解以及实现一套微服务对外发布API管理平台 | 项目开发中常用的设计模式整理 | 异构语言调用平台的设计与实现 | 大话正则表达式 | 云API平台的设计与实现 | 个税改了,工资少了,不要慌!文末附计算器
关注我们的公众号
长按识别二维码关注我们





