乐趣区

关于electron:万物皆可快速上手之Electron第一弹


最近在开发一款桌面端利用,用到了 ElectronReact

React作为日常应用比拟频繁的框架,这里就不具体阐明了,这里次要是想通过几篇文章让大家疾速上手 Electron 以及与 React 完满交融。

本篇是系列文章的第一篇,次要是给大家分享 Electron 的一些概念,让大家对 Electron 有一个初步的认知。

先来理解一下什么是 Electron 吧,可能很多小伙伴还没有听过Electron,置信很多小伙伴此时的表情是这样的:

看下官网的自我介绍:

Electron 是一个能够应用 Web 技术如 JavaScriptHTMLCSS 来创立跨平台原生桌面利用的框架。借助 Electron,咱们能够应用纯 JavaScript 来调用丰盛的原生 APIs

Electronweb 页面作为它的 GUI,而不是绑定了 GUI 库的 JavaScript。它联合了 ChromiumNode.js 和用于调用操作系统本地性能的 APIs(如关上文件窗口、告诉、图标等)。

下面这张图很好的阐明了 Electron 的弱小之处。

正因如此,当初曾经有很多由 Electron 开发的利用,比方 AtomVisual Studio Code 等。咱们能够在 Apps Built on Electron 看到所有由 Electron 构建的我的项目。

疾速开始

后面说了那么多 废话 ,上面进入正题,带大家用五分钟(为什么是五分钟?我猜的 ????) 的工夫运行一个 ElectronHello World

装置

这一步很简略:

npm install electron -g

第一个 Electron 利用

一个最简略的 Electron 利用目录构造如下:

hello-world/
├── package.json
├── main.js
└── index.html

package.json的格局和 Node 的完全一致,并且那个被 main 字段申明的脚本文件是你的利用的启动脚本,它运行在主过程上。你利用里的 package.json 看起来应该像:

{
  "name": "hello-world",
  "version": "0.1.0",
  "main": "main.js"
}

创立 main.js 文件并增加如下代码:

const {app, BrowserWindow} = require("electron");
const isDev = require("electron-is-dev");
const path = require("path");
let mainWindow;

app.on("ready", () => {
  mainWindow = new BrowserWindow({
    width: 1024,
    height: 680,
    webPreferences: {
      nodeIntegration: true,
      // https://stackoverflow.com/questions/37884130/electron-remote-is-undefined
      enableRemoteModule: true,
    },
  });
  // https://www.electronjs.org/docs/api/browser-window#event-ready-to-show
  // 在加载页面时,渲染过程第一次实现绘制时,如果窗口还没有被显示,渲染过程会收回 ready-to-show 事件。在此事件后显示窗口将没有视觉闪动
  mainWindow.once("ready-to-show", () => {mainWindow.show();
  });
  const urlLocation = `file://${__dirname}/index.html`;
  mainWindow.loadURL(urlLocation);
});

而后是 index.html 文件:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Hello World!</title>
    <style media="screen">
      .version {color: red;}
    </style>
  </head>
  <body>
    <h1>Hi! 我是柯森!</h1>
  </body>
</html>

到这里main.jsindex.htmlpackage.json 这几个文件都有了。万事俱备,来运行这个我的项目。因为后面曾经全局装置了electron,所以咱们能够应用 electron 命令来运行我的项目。在 hello-world/ 目录外面运行上面的命令:

$ electron .

你会发现会弹出一个 electron 利用客户端,如图所示:

到这里,咱们曾经实现了一个最简略的electron 利用。

但你肯定会对下面用到的一些 api 有纳闷,上面我将带大家深入浅出的理解一下 electron 的罕用概念和api

相干概念

Electron 的过程分为主过程和渲染过程。在说这个之前,我感觉有必要先说一下过程和线程的概念。

过程和线程

这里参考的是廖雪峰老师对于过程和线程概念的论述,我感觉说的清晰明了。

对于操作系统来说,一个工作就是一个过程(Process),比方关上一个浏览器就是启动一个浏览器过程,关上一个记事本就启动了一个记事本过程,关上两个记事本就启动了两个记事本过程,关上一个 Word 就启动了一个 Word 过程。

有些过程还不止同时干一件事,比方Word,它能够同时进行打字、拼写查看、打印等事件。在一个过程外部,要同时干多件事,就须要同时运行多个“子工作”,咱们把过程内的这些“子工作”称为线程(Thread)。

主过程和渲染过程

主过程

electron 外面,运行 package.json 外面 main 脚本的过程被称为 主过程。主过程管制整个利用的生命周期,在主过程中能够创立 Web 模式的 GUI,而且整个 Node API 是内置其中。

渲染过程

因为 Electron 应用 Chromium 来展现页面,所以 Chromium 的多过程架构也被充分利用。每个 Electron 的页面都在运行着本人的过程,这样的过程咱们称之为 渲染过程

在个别浏览器中,网页通常会在 沙盒环境 下运行,并且不容许拜访原生资源。然而,Electron 用户领有与底层操作系统间接交互的能力。

主过程与渲染过程的区别

主过程应用 BrowserWindow 实例创立页面。每个 BrowserWindow 实例都在本人的渲染过程里运行页面。当一个 BrowserWindow 实例被销毁后,相应的渲染过程也会被终止。

主过程治理所有页面和与之对应的渲染过程。每个渲染过程都是互相独立的,并且只关怀他们本人的页面。

electron 中,页面不间接调用底层 APIs,而是通过主过程进行调用。所以如果你想在网页里应用 GUI 操作,其对应的渲染过程必须与主过程进行通信,申请主过程进行相干的 GUI 操作。

electron 中,主过程和渲染过程的通信次要有以下几种形式:

  • ipcMain、ipcRender
  • Remote 模块

过程通信将稍后在下文具体介绍。

BrowserWindow 的创立

BrowserWindow用于创立和管制浏览器窗口。像下面的 hello-world 中:

mainWindow = new BrowserWindow({
  width: 1024,
  height: 680,
  webPreferences: {
    nodeIntegration: true,
    // https://stackoverflow.com/questions/37884130/electron-remote-is-undefined
    enableRemoteModule: true,
  },
});

const urlLocation = `file://${__dirname}/index.html`;
mainWindow.loadURL(urlLocation);

创立了一个 1024*680 的窗口,并通过 loadURL 办法来加载了一个本地的 html 文件。

这里个别会通过辨别环境加载对应不同的文件。

过程间的通信

在计算机系统设计中,不同的过程间内存资源都是互相隔离的,因而过程间的数据交换,会应用过程间通信形式达成。而不同于个别的原生利用开发,Electron 的渲染过程与主过程别离属于独立的过程中,而且过程间会存在频繁的数据交换,这时抉择一个正当的过程间通信形式显得尤为重要。上面是 Electron 中官网提供的过程间通信形式:

window.postMessage,LocalStorage

在前端开发中,鉴于浏览器对本地数据有严格的拜访限度,所以个别通过该两种形式进行窗口间的数据通讯,该形式同样实用于 Electron 开发中。然而因为 API 设计目标仅仅是为了前端窗口间简略的数据传输,大量以及频繁的数据通讯会导致利用构造涣散,同时传输效率也值得狐疑。

应用 IPC 进行通信

Electron 中提供了 ipcRenderipcMain 作为主过程以及渲染过程间通信的桥梁,该形式属于 Electron 特有传输方式,不适用于其余前端开发场景。Electron 沿用 Chromium 中的 IPC 形式,不同于 sockethttp 等通信形式,Chromium 应用的是命名管道 IPC,可能提供更高的效率以及安全性。

主过程收发信息

具体参考ipcMain

  • 主过程接管渲染过程发送的信息
ipcMain.on("message", (e, msg) => {console.log(msg);
});
  • 主过程(主窗口)发送信息给渲染过程
mainWindow.webContents.send('message', { name: 'from the main by cosen'});

渲染过程收发信息

通过 ipcRenderer 发送或接管

  • 渲染过程接管主过程发送的信息
ipcRenderer.on("message", (e, msg) => {console.log(msg);
});
  • 渲染过程发送信息给主过程
ipcRenderer.send("message", { name: "Cosen"});

应用 remote 实现跨过程拜访

remote 模块提供了一种在渲染过程(网页)和主过程之间进行过程间通信(IPC)的简便路径。

Electron中, 与 GUI 相干的模块(如 dialog, menu 等)只存在于主过程,而不在渲染过程中。为了能从渲染过程中应用它们,须要用 ipc 模块来给主过程发送过程间音讯。应用 remote 模块,能够调用主过程对象的办法,而无需显式地发送过程间音讯。

总结

本大节咱们大略的理解了 Electron 的一些概念以及运行了一个入门的 hello-world 程序。但这远远还不够,下一节我会讲一下如何将 ElectronReact完满交融,毕竟还是要更贴近业务的~

好了,不早了,我要去开启我的网易云时光了 ????

❤️ 爱心三连击

1. 如果感觉这篇文章还不错,来个 分享、点赞、在看 三连吧,让更多的人也看到~

2. 关注公众号 前端森林,定期为你推送陈腐干货好文。

3. 非凡阶段,带好口罩,做好集体防护。

退出移动版