2.electron入门之remote的使用

2,137 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

remote概述

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

Electron中, 与GUI相关的模块(如 dialog, menu 等)只存在于主进程,而不在渲染进程中 。为了能从渲染进程中使用它们,需要用ipc模块来给主进程发送进程间消息。使用 remote 模块, 可以调用主进程对象的方法,而无需显式地发送进程间消息 ,这类似于 Java 的 RMI。 下面是从渲染进程创建一个新窗口的例子:

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>electron test</title>
  </head>
  <body>
    electron demo
    <button id="btn">添加新的窗口</button>
    <script>
      const { log } = console
      // 导入 remote 中的  BrowserWindow
      const { BrowserWindow } = require('electron').remote
​
      const btn = document.getElementById('btn')
      btn.onclick = () => {
        let newWin = new BrowserWindow({
          width: 800,
          height: 600,
        })
        win.loadFile('index.html')
        newWin.on('close', () => {
          newWin = null
        })
      }
    </script>
  </body>
</html>

上边的例子就是利用remote中的BrowserWindow来创建一个新的窗口。

远程对象

remote模块返回的每个对象(包括函数)都代表了主进程中的一个对象(我们称之为远程对象或者远程函数)。 当调用远程对象的方法、执行远程函数或者使用远程构造器(函数)创建新对象时,其实就是在发送同步的进程间消息。

在上面的例子中, BrowserWindow 和 win 都是远程对象,然而 new BrowserWindow 并没有在渲染进程中创建 BrowserWindow 对象。 而是在主进程中创建了 BrowserWindow 对象,并在渲染进程中返回了对应的远程对象,即 win 对象。

请注意只有 可枚举属性 才能通过 remote 进行访问。

remote 模块还有以下方法:

image.png

除了使用内置的属性,remote也可以在主进程通过global添加全局变量,通过remote.getGlobal(name)方式获取变量以及方法。

(也可以挂载到app上,app[name] = XXX, const XXX= remote.app.XXX )

主进程:

// global挂载方式
global.message = '主进程的信息';
global.getUserName = () => {
    return '张三'
}

// app挂载方式
app.message = '主进程的信息';
app.getUserName = () => {
    return '张三'
}

渲染进程:

const { getGlobal, app } = require("electron").remote;
console.log('getGlobal获取message---', getGlobal('message')); 
console.log('getGlobal获取getUserName---',getGlobal('getUserName')())
​
console.log('app获取message---', app.message)
console.log('app获取getUserName---', app.getUserName())

结果如下:

image-20220407110651246.png

远程对象的生命周期

Electron 确保在渲染进程中的远程对象存在(换句话说,没有被垃圾收集),那主进程中的对应对象也不会被释放。 当远程对象被垃圾收集之后,主进程中的对应对象才会被取消关联。

如果远程对象在渲染进程泄露了(即,存在某个表中但永远不会释放),那么主进程中的对应对象也一样会泄露, 所以你必须小心不要泄露了远程对象。

不过,主要的值类型如字符串和数字,是传递的副本。

注意问题:

这里需要划下重点,上一章说过,electron的版本发布比较频繁,这就导致了不同版本API的差异问题,导致某些内置对象的使用方法不同!

这里只对remote使用方法做出说明:

electron version < 10

const { XXX } = require("electron").remote;

electron version >= 10

通过require("electron").remote方法引入并没有问题,但是使用时会报错。

image-20220407102319640.png

此前版本中我们使用electron中的remote模块时,不需在主进程的窗口中加入enableRemoteModule:true参数就能够调用remote模块,而在electron 10中,我们需要加入该参数才能调用该模块。

new BrowserWindow({
    webPreferences:{
        nodeIntegration:true, // 启用Node
        enableRemoteModule:true // 启用remote
    }
})

electron version >= 14

在此版本中,electron已经取消了 remote 模块,因此采用上边的写法会报错 undefined.

官方文档如下:

image-20220407102758486.pngremote模块在 Electron 12 中已弃用,并将在 Electron 14 中删除。它被 [@electron/remote]模块取代。

具体原因参考:zhuanlan.zhihu.com/p/406184033

第一步

通过npm安装remote

`npm install --save @electron/remote`

第二步

在主进程文件里引入,相当于初始化`remote`,使得渲染程序能够和主程序进行通讯。

`require('@electron/remote/main').initialize()`

第三步

在渲染程序中写入:

`const { BrowserWindow } = require('@electron/remote')`

后续可能还会发布新的版本,所以对于electron的版本选择以及使用,需要常看更新文档哟!

感谢

谢谢你读完本篇文章,希望对你能有所帮助,如有问题欢迎各位指正。

我是Nicnic,如果觉得写得可以的话,请点个赞吧❤。

写作不易,「点赞」+「在看」+「转发」 谢谢支持❤

往期好文

《Javascript高频手写题1.0》

《Vue中生成图片验证码的小组件》

《前端JS高频面试题---1.发布-订阅模式》

《前端JS高频面试题---2.单例模式》

《前端JS高频面试题---3.代理模式》

《前端JS高频面试题---4.策略模式》

《前端CSS高频面试题---1.CSS选择器、优先级、以及继承属性》

《前端CSS高频面试题---2.em/px/rem/vh/vw的区别》

《前端CSS高频面试题---3.如何实现两栏布局,右侧自适应?三栏布局中间自适应呢?》