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下必须显式定义复制粘贴. 解题思路在这儿
定义的方式是在菜单中添加复制/粘贴选项.

标签: none 阅读量: 1006

添加新评论