只需五分钟,就会Electron

关于Electron

Electron是由Github开发,用HTMLCSSJavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将Chromium和 Node.js 合并到同一个运行时环境中,打包出可以运行在MacWindowsLinux系统下的应用。

核心理念:

  • 为了保持Electron的小 (文件体积) 和可持续性 (依赖和API的扩展) ,Electron限制了使用的核心项目的范围。
  • Electron只用了Chromium渲染库 而不是 全部。
  • Electron所添加的的新特性应主要用于原生API(node.js)。

Chromium是什么?

Chromium是由Google主导开发的网页浏览器,说明白点:

Chromium是Chrome浏览器背后的引擎。

几个无聊的联想

Chromium + Node.js = ?

如果把 浏览器Node.js 联系在一起,一般想到的一个web服务,TCP以及其衍生协议充当了页面服务器通信的桥梁。

Web + Native = ?

浏览器可以调用原生功能,很容易让人联想到Hybrid,web通过自定义的桥接协议与Native通信,Native拦截请求从而得知web需要调用的功能。

Electron的原理是什么?

在一个Electron桌面应用分成两个进程:

  • 主进程 —— MainProcess
  • 渲染进程 —— RenderProcess

主进程负责管理原生操作,例如: 文件读写,图形处理,程序开关等,同时还管理渲染进程以及应用的生命周期。

渲染进程通过 Chromium 绘制前端界面,用户可以在页面上触发事件。

那么,Node.js 如何与Chromium通信?

答案是 IPC——进程间通信。

Electron IPC通信模型

Electron IPC提供了基于事件的API,在渲染进程和后台进程中都可以向对方发送事件,也可以在事件处理函数中通过发送的新的事件回复对方:

  • 通过EventEmitter实例向对方发送事件
  • 发送事件需要制定对方句柄,不支持全局广播
  • 支持同步事件和异步事件

创建一个桌面应用

Step 1. 环境

  • Node.js = 8.x | 9.x

Step 2. 安装electron包

npm install electron --save-dev --save-exact
复制代码

如果下的慢,可以尝试淘宝镜像。

Step 3. 项目结构

.
└── app├── main.js├── index.js├── index.html├── package.json
复制代码

main.js 是主进程执行文件, index.html 和 index.js 是渲染进程的视图,和平时写的网页一样。

需要在package.json写明App名称等信息,同时 需要指定入口文件(即main.js),举个例子:

{"name": "app","productName": "app","version": "0.0.1","main": "./app/index.js"
}
复制代码

更详细的范例可以参照官方示例:electron-quick-start

Step 4. 启动electron

主进程服务加上npm scripts:

"dev:electron-main": "cross-env NODE_ENV='development' electron -r babel-register ./",
复制代码

启动主进程:

npm run  dev:electron-main
复制代码

Step 5. 开发

electron主进程文件修改之后需要重启应用才能生效,每次手动重启不方便,推荐使用鄙人抖机灵撸的一个包:

electron-watch

食用方法,在主进程文件中插入下面代码片段:

if (process.env.NODE_ENV === 'development') {require('electron-watch')(__dirname,'dev:electron-main', // means: npm run dev:electron-mainpath.join(__dirname, './'),);
}
复制代码

** PS: 该库Windows上有bug,正确的食用发放是只按一次Ctrl+S,同时按几次会重启多个应用。 **


electron模块

electron提供了丰富的API让你调用原生的功能,参见electron文档。

但是过一下下面这几个模块,就可以快速撸出一个Electron App。

1. app

一个桌面应用对象,提供API控制应用,同时可以监控应用程序的事件生命周期。

例如在最后一个窗口被关闭时退出应用:

const {app} = require('electron');
app.on('window-all-closed', () => {app.quit();
});
复制代码

可以监控的生命周期事件:

  • will-finish-launching:当应用程序完成基础的启动的时候被触发
  • ready: 当 Electron`: 完成初始化时被触发
  • window-all-closed:当所有的窗口都被关闭时触发
  • before-quit:在应用程序开始关闭窗口之前触发
  • will-quit: 当所有窗口都已关闭并且应用程序将退出时发出
  • quit:在应用程序退出时发出

2. BrowserWindow

一个浏览器窗口

创建一个浏览器窗口:

import { app, BrowserWindow } from 'electron';app.on('ready', () => {const win = new BrowserWindow({width: 800, height: 600});// 加载远程URLwin.loadURL('https://www.coolecho.net'); // 或加载本地HTML文件win.loadURL(`file://${__dirname}/app/index.html`);
});
复制代码

父子窗口:

const {BrowserWindow} = require('electron');const top = new BrowserWindow();
/*** 加上model属性,子窗口为模态窗口,父窗口被禁用*/
const child = new BrowserWindow({parent: top})
child.show()
top.show()
复制代码

child 窗口将总是显示在 top 窗口的顶部,长得像这个样子:

3. ipcMain & ipcRender

ipcMainEventEmitter类的一个实例。 当在主进程中使用时,ipcRender处理从 渲染器进程(网页) 发送出来的异步和同步信息。 从渲染器进程发送的消息将被发送到该模块。

ipcRenderer也是一个 EventEmitter 的实例。 你可以使用它提供的一些方法从渲染进程 (web 页面) 发送同步或异步的消息到主进程。 也可以接收主进程回复的消息。

下面是在渲染和主进程之间发送和处理消息的一个例子:

// 在主进程中
const {ipcMain} = require('electron');// 异步
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'
});
复制代码
//在渲染器进程 (网页) 中
const {ipcRenderer} = require('electron');// 同步请求
console.log(ipcRenderer.sendSync('synchronous-message', 'ping'));// 异步发送请求
ipcRenderer.on('asynchronous-reply', (event, arg) => {console.log(arg) // prints "pong"
});
// 异步接收返回
ipcRenderer.send('asynchronous-message', 'ping');
复制代码

你可以通过ipcMainipcRenderer模块,在渲染页面中调用原生功能处理一些事物,当然electron做到的远不止这些,它还提供了remote模块。使用 remote 模块, 你可以调用 主进程对象 的方法, 而不必显式发送进程间消息。

4. Menu

创建原生应用菜单和上下文菜单。

import { Menu } from 'electron';const menuTemplete = [{label: 'File',submenu: [{label: 'New Note',accelerator: 'CmdOrCtrl+N',enabled: false,// role: 'new file',click: () => mainWindow.webContents.send('new-file', 1),}, {label: 'New Project',accelerator: 'Shift+CmdOrCtrl+N',enabled: false,// role: 'new project',click: () => mainWindow.webContents.send('new-project'),}, {type: 'separator',}, {label: 'Save',accelerator: 'CmdOrCtrl+S',role: 'save',enabled: false,click: () => mainWindow.webContents.send('save-content'),}],}];const menu = Menu.buildFromTemplate(menuTemplete);Menu.setApplicationMenu(menu);
复制代码

效果:

还可以创建Context菜单:

const menu = new Menu();menu.append(new MenuItem({label: 'Rename',click: () => mainWindow.webContents.send('rename-project'),
}));
menu.append(new MenuItem({label: 'Delete',click: () => mainWindow.webContents.send('delete-project'),
}));
menu.append(new MenuItem({type: 'separator',
}));
menu.append(new MenuItem({label: 'New Notebook', click: () => mainWindow.webContents.send('new-project'),
}));// 项目右键菜单
ipcMain.on('show-context-menu-project-item', (event) => {const win = BrowserWindow.fromWebContents(event.sender);menu.popup(win);
});
复制代码

效果:

菜单项

Electron提供了很多属性来定制一个菜单项,例如上面例子中的labelclick,role等等:

  • click: 点击菜单项的回调方法
  • role: Electron定制的内置事件,有click的时候,此项将被忽略
  • type: 可以是 normalseparatorsubmenucheckboxradio
  • label: 菜单名称,当设置role时默认为role
  • accelerator: 定义快捷键
  • icon
  • sublabel
  • enabled: 如果为 false,该菜单项将会置灰且不可点击
  • visible: 控制菜单项是否可见
  • checked: 控制菜单项是否选中,typechckboxradio时有效
  • submenu: 定义子菜单项
  • id: 可以通过它来引用该菜单项
  • position: 允许对给定菜单中的特定位置进行细粒度定义(没试过)

其他模块

基本上知道上诉三个模块,就可以开发一个Electron APP了,但Electron的模块远远不止这些,它还囊括网络、电源、通知、进程、菜单、本地化、协议、会话、Shell等等模块,详细的介绍参阅Electron文档。


分发应用

应用开发完了,接下来得打包了。

有三种种打包方式:

  1. 手动打包
  2. 打包工具
  3. 通过重编译源代码来进行重新定制

1,3两种方式有点繁琐,这里介绍几个常用的打包工具:

  • electron-packager
  • electron-forge
  • electron-builder

如果想在APP STORE上架应用,,这需使用XCode填写证书和开发者信息,手动打包。

我用的是electron-packer,打包起来十分方便,看看npm script

"packager:mac": "electron-packager ./lib Yosoro --overwrite --platform=darwin --arch=x64 --out=out --icon=assets/icons/osx/app.icns",
"packager:win": "electron-packager ./lib Yosoro --overwrite --platform=win32 --arch=ia32 --out=out --icon=assets/icons/win/app.ico",
"packager:linux": "electron-packager ./lib Yosoro --overwrite --platform=linux --arch=x64 --out=out",
复制代码

--icon参数是用来指定应用的logo的,macOS下是.icns格式, Windows下是.ico格式。

为啥Linux的没有这个命令行参数呢?

因为Linux的Logo需要在初始化Electron应用的时候指定,格式为PNGJPEG,建议使用PNG

const options = {title: 'Yosoro',width: 1180,height: 786,
};
if (process.platform === 'linux') { // 加上logooptions.icon = path.join(__dirname, './resource/app.png');
}
mainWindow = new BrowserWindow(options);
复制代码

options.icon这个属性在macOSWindows下是无效的。

最后,你以为直接npm run这三条命令就完事了吗?

electron-packager只在对的地方干对的事,例如,在macOS上只打macOS上运行的包,Windows上只打Windows上运行的包,从不会干多余的打包工作。比如在macOS下会直接打成一个APP包:

如果你想分别打三端的包,需要分别在macOSWindowsLinux这三个环境下打包。

总结

关于Electron还有非常强大的功能,例如热更新等等,本文只是菜鸡随手笔记,有错误的地方欢迎指正。

最后,关于Electron结合react的实例 戳这里,求star。

利用Electron构建桌面应用相关推荐

  1. ZEGO教程:如何通过electron构建桌面跨平台音视频应用

    近年来,视频直播.短视频.在线教育.在线医疗.人工智能.以及VR等视频领域的相关行业都非常热门,成为大众瞩目的焦点.而5G网络的相继普及,移动网速飞速提升,又将引起下一轮视频应用的革命. 可以看到,在 ...

  2. 使用 AngularJS 和 Electron 构建桌面应用

    使用 AngularJS 和 Electron 构建桌面应用 GitHub 的 Electron 框架(以前叫做 Atom Shell)允许你使用 HTML, CSS 和 JavaScript 编写跨 ...

  3. AngularJS 和 Electron 构建桌面应用

    译]使用 AngularJS 和 Electron 构建桌面应用 原文: Creating Desktop Applications With AngularJS and GitHub Electro ...

  4. 使用 Electron 构建桌面应用程序的介绍

    事实上的团队协作软件,Visual Studio Code - 在撰写本文时市场上最受欢迎的代码编辑器之一,以及WhatsApp的桌面版本都有一个共同点:它们都是用Electron构建的.js.随着这 ...

  5. 使用 Electron 构建桌面应用

    作者:kmokidd 链接:https://zhuanlan.zhihu.com/p/20225295 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 译者注:前一段 ...

  6. 【译】使用 AngularJS 和 Electron 构建桌面应用

    原文:Creating Desktop Applications With AngularJS and GitHub Electron GitHub 的 Electron 框架(以前叫做 Atom S ...

  7. 如何利用 Electron 把网页变成桌面程序

    正如 Electron 官方所说"如果你可以建一个网站,你就可以建一个桌面应用程序". 作为一个跨平台的桌面应用开发框架,Electron 的迷人之处在于,它是建立在 Chromi ...

  8. Electron开发桌面应用

    由 Bazzzinga威 同学翻译自 Medium.https://medium.com/developers-writing/building-a-desktop-application-with- ...

  9. html getelementbyid 修改图片_如何使用HTML、CSS和JS轻松构建桌面应用程序

    HTML,CSS和JavaScript语言是否可以真正用于构建桌面应用程序? 答案是肯定的. 在这篇文章中,我们将主要关注Electron如何使用HTML.CSS和Javascript等网络技术来创建 ...

最新文章

  1. 【课堂笔记系列】二进制
  2. Python OpenCV GrabCut进行前景分割和提取
  3. 机器学习中常见的过拟合解决方法
  4. 20年老码农分享20条编程经验,你pick哪些?
  5. python输入输出-Python3输入输出
  6. python_ re模块学习
  7. 驱动编程中的头文件与内核源码的关系
  8. kafka消费的三种模式_快速认识Kafka
  9. servlet的理解
  10. Oracle PL/SQL语言初级教程
  11. python聚类分析结果很差_python中的聚类分析:value错误:x和y的大小必须相同
  12. c# 开发window服务
  13. 程序员开发软件的意义到底在哪?
  14. python123用户登录的三次机会_用户登录三次机会(PYTHON)
  15. 力扣-1232 缀点成线
  16. 使用EDD枚举域数据
  17. 蜗牛星际NAS安装黑群晖V6.2.1+洗白+免U盘引导启动
  18. arm9开发板学习笔记之程序烧录
  19. 消息轨迹、ACL 与多副本搭建
  20. 用turtle作画玩一玩吧

热门文章

  1. 德州仪器发家史:分拆和并购的大师级玩家
  2. 简要评说Adobe的FlashPlayer的渲染算法--续1
  3. 6.近体诗的首句入韵与衬韵
  4. Python pow 函数- Python零基础入门教程
  5. 军职在线大学生计算机基础,军职在线演讲与口才答案第一章
  6. 成都拓嘉辰丰:商家在申请多多买菜提货点时该如何做?
  7. 解决阿里云服务器被植入挖矿脚本过程
  8. M1 Macbook air IDEA中svn不能用问题
  9. 农历置闰新算法:大宇历法
  10. java tuple_Java元组Tuple使用实例