关于Electron

官网:Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 ChromiumNode.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需要本地开发 经验。

即浏览器可以展示的网页,都可以通过electron打包成桌面app。

5分钟构建一个桌面webApp

环境配置

  • nodejs

项目初始化

下载完nodejs后既可以使用npm
初始化项目命令:npm init -y,项目下会生成一个 package.json 文件
image.png
需要将里面的内容做些修改:

{
  "name": "electron_quick_start",
  "version": "1.0.0",
  "description": "",
  "main": "main.js", //修改
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

安装依赖包

因为要安装的 electron 很大,如果不将镜像源换为国内的话,会很慢,还可能会报错,可以将 electron 镜像源改为淘宝的。
可以使用命令:config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/
然后下载 electron:npm i electron -D

注意:electron 必须安装在开发依赖中,否则无法启动。
image.png

配置入口界面(index.html)

可以先随便写点元素:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hi I'm Martin</h1>
  </body>
</html>

配置入口文件(main.js)

首先要引入 electron 中的 app 、BrowserWindow 组件。

  • app:控制整个electron应用的声明周期,包含了各种钩子函数和监听事件
  • BrowserWindow:创建和管理应用程序窗口
const { app, BrowserWindow } = require('electron')

创建一个窗体实例,定义好其大小和入口界面的文件地址

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 800
  })
  win.loadFile('index.html');
}

在 app 的 ready 事件触发后激活窗口(调用createWindow函数),可以使用 app.whenReady 来监听此事件。

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

通过生命周期维护应用在个平台的原生效果

窗口关闭后退出应用:

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

如果应用程序启动了,但是没有产生窗口,则启动一个窗口:

因为窗口无法在 ready 事件之前创建,所以应该在应用初始化之后监听,且仅能监听 'active' 事件:

app.whenReady().then(()=>{
  createWindow();
  if(BrowserWindow.getAllWindows().length === 0) createWindow();
})

到这一步,创建一个桌面 webapp 最基本的配置已经结束了。

运行项目

还需要做一步配置,在 package.json 中新添一个脚本,通过 electron 运行项目。

{
  "name": "electron_quick_start",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "electron ."
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron": "^20.1.0"
  }
}

此时,在终端输入npm start命令,不出意外的话就可以看到以下界面。
image.png

配置与加载器(preload.js)

什么是与加载器?

现在有一个需求,需要将Node、Electron、Chrome的版本号展示在页面上,应该怎么做?

  • 直接在main.js主进程中操作dom吗?
  • 还是说在html中去调用main.js的数据?

现在要分清楚的是:Nodejs进程和浏览器的渲染引擎进程不是同一个进程,是无法互相调用的,这个时候就需要预加载器。
预加载器在渲染进程之前加载,并有权访问 渲染器全局 和 Nodejs环境
通俗的讲就是,预加载器就是二者之间联系的桥梁。
配置preload.js

window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})

以上代码所作的工作就是,定义一个替换标签内容的脚本,然后读取Nodejs中的process.versions对象,将取得的对象通过脚本将对应的标签赋值为对应的版本号。
要让此预加载器生效,需要在主进程中 BrowserWindow构造器中传入:

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
  })
  win.loadFile('index.html');
}
  • __dirname:当前脚本的路径的字符串
  • path.join:将多个路径整合在一起,创建一个跨平台的路径字符串(因为程序不光会在windows跑,也会在linux、mac上跑,其路径链接的斜杠是不一样的。

除此之外还需再html中加入带有以上id的标签:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hi I'm Martin</h1>
    chrome:v<span id="chrome-version"></span> node:v<span
      id="node-version"
    ></span>
    electron:v<span id="electron-version"></span>
  </body>
</html>

运行项目,可看到环境的版本号:
image.png

总结

关于Electron:一个可以将网站打包为桌面webapp的框架
创建一个桌面webapp的步骤:

  • 创建一个nodejs程序,依赖包包含electron
  • 创建一个main.js作为入口文件,index.html作为入口界面
  • 为了渲染器可以访问nodejs中的某些属性、配置,需要使用preload预加载器