electron - 基于nodejs和chromium的跨平台桌面应用

官方:

Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。

个人理解:

electron就是一个nodejs应用程序,然后使用了chromium作为他的GUI视图,它可以使用纯javascript调用原生操作系统的api来创建桌面应用,使用javascript,html和css渲染视图。

精简版理解

所以你能把它看作成一个被 JavaScript 控制的,精简版的 Chromium 浏览器。

electron应用

1) 先初始化一个node应用

1
npm init -y

这样就生成一个package.json文件

1
2
3
4
5
{
"name": "your-app",
"version": "0.1.0",
"main": "index.js",
}

2) main指定node程序的主入口,如果没有指定就加载当前根目录下的index.js

1
2
3
4
5
{
"name": "your-app",
"version": "0.1.0",
"main": "main.js" // 修改程序的主入口
}

3) 通过npm的node package manager安装electron包

1
npm install --save-dev electron

4) 添加scripts脚本引导node去执行当前的electron应用

1
2
3
4
5
6
7
8
{
"name": "your-app",
"version": "0.1.0",
"main": "main.js",
"scripts":{
"start":"electron ."
}
}

5) 本地开发可以使用nodemon(node monitor)来监听本地文件变化触发热更新

1
2
3
4
5
6
7
8
9
10
11
// 安装nodemon
npm install nodemon -D
// 编写npm脚本
{
"name": "your-app",
"version": "0.1.0",
"main": "main.js",
"scripts":{
"start":"nodemon --watch main.js --exec electron ." // 监听main.js文件变化后执行electron .
}
}

项目搭建

  • 可以使用 electron-forge的脚手架cli工具初始化一个项目,然后使用electron-builder将程序打包成不同的安装包

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // 安装prebuild依赖
    npm install electron-prebuilt-compile -g --registry=https://registry.npm.taobao.org
    // 安装
    npm i electron-forge -g --registry = https: //registry.npm.taobao.org
    // init项目
    electron-forge init my-first-electron
    // cd
    cd my-first-electron
    // run
    npm start
  • 也可以clone官方的electron-quick-start项目,npm install&&npm start就可以跑起来一个简单的electron项目

应用架构

mainProcess 主进程

  • 在package.json中配置的main脚本就是一个主进程
  • electron应用有且只有一个主进程
  • 主进程通过nodejs的api可以调用底层原生api(普通浏览器在沙盒模型中无法访问操作系统的原生资源)
  • 可以通过ipcMain和渲染现成通信
  • 可以操作nodejs和dom的api

    renderProcess 渲染进程

  • 可以有一个或多个渲染进程
  • 可以操作nodejs和dom的api
  • 可以通过ipcRenderer和主进程通信

代码演示

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
// 主进程
const {app,BrowserWindow} = require('electron') // 只能在主进程中使用
app.on('ready',()=>{
const mainWindow = new BrowserWindow({ // 主进程使用 BrowserWindow 实例创建页面
width:800,
height:600
})
mainWindow.loadFile('./index.html') // 每个 BrowserWindow 实例都在自己的渲染进程里运行页面
})

// index.html
<body>
<div id="content">暂无数据</div>
<button id="btn">点我</button>
</body>
<script>
require('./index.js') // 渲染进程,使用nodejs的api
</script>

// index.js
const {BrowserWindow} = require('electron').remote; // 通过remote可以在渲染进程中引入BrowserWindow创建页面
等价于
const {remote} = require('electron')
const {BrowserWindow} = remote;

const renderWindow = new BrowserWindow()

从上面代码可以看见:在主进程中通过electron.BrowserWindow创建了渲染进程的实例页面

主线程和渲染线程通信

  • 通过ipcMain和ipcRenderer的事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 主进程
const {app,BrowserWindow,ipcMain} = require('electron')
app.on('ready',()=>{
const mainWindow = new BrowserWindow({
width:800,
height:600
})
mainWindow.send('sendToRenderProcess','i am from mainProcess') // 主进程发送事件
})
或者

// 监听从渲染进程发送过来的事件
ipcMain.on('sendFromRender',(event,arg)=>{
// 向渲染进程发送事件
event.render.send('sendToRenderProcess','i am from mainProcess')
})
ipcMain.on('sendFromRenderProcess',(event,msg)=>{
console.log(msg) // i am from renderProcess
})

这样主进程mainProcess的消息就发送给渲染进程renderProcess了

1
2
3
4
5
6
7
8
const {ipcRenderer} = require('electron')
// 渲染选中的列表
ipcRenderer.on('sendToRenderProcess', (event, msg) => {
// 接收从主进程发送过来的事件
console.log(msg) // i am from mainProcess
// 向主进程发送事件
ipcRenderer.send('sendFromRenderProcess','i am from renderProcess')
})
初到贵宝地,有钱的给个钱场,没钱的挤一挤给个钱场