一起养成写作习惯!这是我参与「掘金日新计划 · 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
模块还有以下方法:
除了使用内置的属性,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())
结果如下:
远程对象的生命周期
Electron 确保在渲染进程中的远程对象存在(换句话说,没有被垃圾收集),那主进程中的对应对象也不会被释放。 当远程对象被垃圾收集之后,主进程中的对应对象才会被取消关联。
如果远程对象在渲染进程泄露了(即,存在某个表中但永远不会释放),那么主进程中的对应对象也一样会泄露, 所以你必须小心不要泄露了远程对象。
不过,主要的值类型如字符串和数字,是传递的副本。
注意问题:
这里需要划下重点,上一章说过,electron的版本发布比较频繁,这就导致了不同版本API的差异问题,导致某些内置对象的使用方法不同!
这里只对remote使用方法做出说明:
electron version < 10
const { XXX } = require("electron").remote;
electron version >= 10
通过require("electron").remote
方法引入并没有问题,但是使用时会报错。
此前版本中我们使用electron中的remote模块时,不需在主进程的窗口中加入enableRemoteModule:true
参数就能够调用remote模块,而在electron 10中,我们需要加入该参数才能调用该模块。
new BrowserWindow({
webPreferences:{
nodeIntegration:true, // 启用Node
enableRemoteModule:true // 启用remote
}
})
electron version >= 14
在此版本中,electron已经取消了 remote 模块,因此采用上边的写法会报错 undefined.
官方文档如下:
该
remote
模块在 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,如果觉得写得可以的话,请点个赞吧❤。
写作不易,「点赞」+「在看」+「转发」 谢谢支持❤
往期好文
《前端CSS高频面试题---1.CSS选择器、优先级、以及继承属性》