electron入门
1. 快速开始
通过electron quick start项目开始是个不错的主意. 需要注意的是, electron体积巨大, 100M~200M, 在我朝使用主意用镜像, 或者使用淘宝的cnpm,替代下面的npm install.
# Clone the Quick Start repository
$ git clone https://github.com/electron/electron-quick-start
# Go into the repository
$ cd electron-quick-start
# Install the dependencies and run
$ npm install && npm start
这时候你应该能看到一个helloworld 和一个打开的chrome dev tools.
2. 最主要的文件和关系
在根目录下, 有main.js ,index.html, renderer.js几个文件,以及node_modules文件夹,还有package.json文件.
首先, electron主要有两块:
a) 与操作系统的一些原生API通讯, 这主要通过main.js调用系统的一些方法和界面.比如显示个菜单, 调起一个打开文件对话框之类的.
b) 建立软件的界面和逻辑, 这主要通过index.html,renderer.js以及其他html架构的文件(以下简称为html架构). 但在这儿不能直接调用系统的资源, 如逆向调起一个打开文件对话框就不行.
是否以main.js为入口, 在package.json中配置, 里面有一行:
"main": "main.js",
当然, 也只有这一个文件,不涉及复杂的文件管理的话, 这个一般也不会去改它.
是否以index.html为入口, 在main.js调起window的时候定义:
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
上面的index.html可以使用相对路径调起其他的html文件, 相对路径的起点为main.js所在的目录.
至于renderer.js, 是通过index.html中的script标签引用的, 这个就熟悉了,不多说了.
3. 在html架构中调用系统资源的第一种方式: 发送事件消息
前面说了html架构中不能直接调用系统资源,调用需要通过main.js进行. 和main.js通讯主要是通过发送event消息.
整个过程是:
* renderer.js中ipc.send()发送事件A
* main.js中ipcMain.on()监听事件A, 监听到后,
* main.js中event.sender.send()发送事件B和附加信息
* renderer.js中ipc.on()监听返回的事件B,处理发回的信息
举例如下: 在main.js中通过ipcMain.on()监听html架构中的renderer.js发来的open-file-dialog事件, 并在监听后调用系统事件,如dialog, 然后通过event.sender.send()回馈selected-directory事件,并携带文件路径:
const { ipcMain } = require('electron')
const { dialog } = require('electron')
ipcMain.on('open-file-dialog', function(event) {
dialog.showOpenDialog({
properties: ['openFile', 'openDirectory']
}, function(files) {
if (files) event.sender.send('selected-directory', files)
})
})
在renderer.js中, 通过ipc.send()发送open-file-dialog事件, 通过ipc.on()监听返回事件selected-directory, 并可以对返回的文件路径做进一步的处理.
const ipc = require('electron').ipcRenderer
ipc.send('open-file-dialog')
ipc.on('selected-directory', function(event, path) {
alert(path)
})
4. 在html架构中调用系统资源的第二种方式. remote
上面的简化写法, 可以直接使用remote调用main.js中才能提供的系统资源.
在renderer.js中:
const remote = require('electron').remote
remote.dialog.showOpenDialog({
properties: ['openFile', 'openDirectory']
}, function(files) {
alert(files)
})
哦,好像感觉好用多了...
5. 在main.js中主动发送事件给html框架
这时候没有renderer.js发过来的事件, 也就没有event.sender.send()提供, 可以用mainWindow, 前提是mainWindow已经创建.
mainWindow.send('some-event')
7. 打包软件
首先要有一份electron的可运行文件包, node_modules\electron\dist中可以找到electron.exe, 这个文件夹就是了.打包这个文件夹发布就可以了.
只要把main.js,package.json, node_modules中你用到的模块,以及其他index.html等html框架下的文件复制到上面文件Resources/app目录下. 然后把electron.exe所在的文件夹打包发布就可以了.
8. 更改图标
windows下有个免费软件resource hacker, 下载来可以用来修改图标.
mac下比较简单. 查看electron.app的信息, 里面的图标可以通过'拷贝'/'粘贴'进行修改的.
mac下打包成dmg, 需要预先把electron.app放到一个文件夹里面, 然后可以通过系统自带的'磁盘工具',点击菜单>文件>新建影像>来自文件夹的影像>选择这个文件夹进行打包.
下面是坑
1号坑 使用第三方npm模块
在html框架中最强大的一个地方就是,不但可以通过script标签引入第三方js使用, 可以通过require使用node.js中提供的模块. 但是注意, 要使用npm install安装,不要使用cnpm install安装, 否则打包后的文件会找不到模块. 原因请看前一篇文章.
2号坑 使用asar打包
可以通过npm install -g asar安装asar打包工具, 对app目录进行打包,这样就不会有一大把的分散文件列在哪儿了, 也避免windows复制node_modules总会出现的长文件名问题.
在resource目录下,命令行执行:
asar pack app app.asar
即可, 执行完后asar包使用起来大多数时候像一个普通目录, 但在如下时候会与普通目录不同
- asar包在运行时是只读的, 所以不能再在运行时修改asar包,比如修改其中的文件, 新建一个文件等,否则你会遇到permission的拒绝的错误.
- 在windows下,asar包中的文件和文件夹可以复制出来, 并粘贴到系统的某处(使用node模块ncp测试过), 但在mac下却不行,原因也是未知啊. 变通的方式是, 你要复制的文件夹就不要放在asar包里面了.
3号坑 菜单
建立的多个一级菜单, 如果有的一级菜单没有子菜单submenu, 而是直接在一级菜单上触发功能, 那么在windows下将显示正常并且触发正常. 但是在mac下只能显示有submenu的.
因此建议所有的一级菜单都要有submenu, 并且不要在一级菜单上触发功能.
另外, mac下面无论什么样的菜单, 第一个菜单都是挂在系统名称下面的.
4号坑 复制粘贴
在Windows下, input和textarea使用Ctrl+C/Ctrl+V复制粘贴正常, 在mac下使用COMMAND+C/V却没有反应. 原因是mac下必须显式定义复制粘贴. 解题思路在这儿
定义的方式是在菜单中添加复制/粘贴选项.