Electron开发初探

技术选型

最开始其实就是想做一个给策划Excel转json的工具,当时考虑了:CocosCreator的插件、直接使用node命令行、做成小软件

CocosCreator插件

一开始考虑的是CocosCreator插件

  1. 技术上没有什么障碍,已经上架了几款小插件。
  2. 相当于一个小软件,提供了可视化的操作。

但有几个问题:

  1. 对使用其它引擎的部门不够友好。
  2. 毕竟是给策划用的,不说装不装CocosCreator,问题是每次操作要打开CocosCreator,这个步骤相对繁琐。
  3. 毕竟有大神插件小王子的excel-killer在那,不敢班门弄斧。

Node

其实node命令行方式,也只是闪下念头,基本不具有可行性。

  1. 不方便,没有可视化界面。
  2. 要装环境,对非技术人员而言比装CocosCreator还要麻烦。

软件形式

  1. 可视化,跨平台,通用
  2. 了解过electron

问题:

  1. 了解=听说过

但,程序猿天生具有喜欢探索折腾的品质,所以选型Electron。

跑通流程

安装electron

本文,默认读者已经有了js开发经验,已经安装好了node环境。官方文档,永远是最好的文档之一

根据官方文档描述,应该要这样安装

1
2
3
mkdir my-electron-app && cd my-electron-app
npm init -y
npm i --save-dev electron

简而言之,就是创建一个目录,并在这个目录下安装electron,当然你全局安装也行,本人并不专注于此,所以选择本地安装。

照着官方文档,创建三个文件,具体解释,可以参考官方文档,此处不做赘述。

  1. index.html 为我们需要的界面

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    </head>
    <body style="background: white;">
    <h1>Hello World!</h1>
    <p>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
    </p>
    </body>
    </html>
  2. preload.js 相当于一个html里面的script

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    window.addEventListener('DOMContentLoaded', () => {
    const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
    }

    for (const type of ['chrome', 'node', 'electron']) {
    replaceText(`${type}-version`, process.versions[type])
    }
    })
  3. 那么界面怎么展示出来的呢?preload.js 和 index.html 又是怎么联系起来的呢?请看main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})

win.loadFile('index.html')
}

app.whenReady().then(() => {
createWindow()

app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})

app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})

调试

package.json中添加一句"scripts": {"start": "electron ."},文件修改如下:

1
2
3
4
5
6
7
8
9
10
{
"name": "my-electron-app",
"version": "0.1.0",
"author": "your name",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron ."
}
}

然后执行npm start即可。

打包

官方文档推荐的是Electron Forge,然而,我怎么都安装不成功,无奈选择放弃。所以这里,我改成使用electron-builder

  1. 安装electron-builder
1
npm install  electron-builder --save-dev
  1. 修改package.json

在scripts中添加 "build": "electron-builder -mw", 完整如下

1
2
3
4
5
6
7
8
9
10
11
{
"name": "my-electron-app",
"version": "0.1.0",
"author": "your name",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder"
}
}
  1. 执行命令
1
npm run build

不知道,各位网络如何,反正我是打包不成功,然后百度下,发现还要从github下载资源,还好,有淘宝镜像提供,继续修改。

  1. 修改镜像

在build下添加"electronDownload":{"mirror":"https://npm.taobao.org/mirrors/electron/"},,完整如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name": "my-electron-app",
"version": "0.1.0",
"author": "your name",
"description": "My Electron app",
"main": "main.js",
"scripts": {
"start": "electron .",
"build": "electron-builder"
},
"build": {
"electronDownload": {
"mirror": "https://npm.taobao.org/mirrors/electron/"
}
},
}

我使用的是mac,执行后生成的dmg,我猜windows应该生成的是exe,不是说好的跨平台吗???就只能生成自己平台的???继续修改2。

  1. 添加打包参数
1
2
3
4
"scripts": {
"start": "electron .",
"build": "electron-builder -mw"
},

至此我们就能打包mac和windows了,其中m代表mac,w代表windows,l代表linux,如果需要linux平台,添加即可。

开发过程中的问题总结

  1. dialog弹不出来

在html中添加了一个按钮,通过按钮点击可以弹起一个dialog,可是怎么也不显示,根据我多年的原生开发经验,感觉可能跟线程有关系,查了一圈也没有个具体说明。还有什么切线程的方法,直接报错。后来还是官方文档,告诉我可以在渲染线程和主线程之间通信。

在渲染线程中

1
2
3
4
5
6
// 导入ipcRenderer
const { ipcRenderer } = require('electron');
// 发送事件
ipcRenderer.send(事件名, 不限参数);
// 监听事件
ipcRenderer.on(事件名, (event, ...args)=>{});

在主线程中

1
2
3
4
5
const { ipcMain } = require('electron');
// 发送事件
ipcMain.send(事件名, 不限参数);
// 监听事件
ipcMain.on(事件名, (event, ...args)=>{});
  1. 选择文件没有回调

有些人的文章是这么写的

1
2
3
dialog.showOpenDialog({
properties: ['openDirectory']
}, (files)=>{})

可是压根没有回调,查询很久,才发现这是旧版本的写法,应该这样写

1
2
3
4
5
dialog.showOpenDialog({
properties: ['openDirectory']
}).then((result) => {
// result:{canceled:boolean, filePaths:string[]}
}).catch();
  1. icon

想给软件添加一个icon,网络答案各式各样,不知道是不是旧版本的原因或者打包工具不一样的原因,查看官方文档发现,非常简单:建一个build目录,然后放一张512像素的icon,命名为:icon.png,这样就可以了。

问题总结

查看官方文档,是解决问题做好的途径,而且不要怕英文,就那几个简单的单词,甚至都不用每个单词看懂,看主要的部分就行了。

说明

因为该工具还不完善,比如还不支持对象嵌套等,暂时就不发出来了,如果想体验下的,可以联系我。