上次写了关于ipc通讯的一些方式,主要都是web页面向主进程通讯,主进程回复通讯,这个感觉和http有点相似,发送一个http资源的请求,服务返回一个资源结果,现在我们主要看这两个点
- 主进程主动推消息给web渲染进程的
- web渲染进程之间的通讯
主进程向渲染进程主动通信
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')
const contents = win.webContents
console.log(contents)
这个创建之后返回的win下面的webContents就是可以渲染和控制web页面的api模块,咱们不会深入展开的,主要针对通讯讲一讲
contents.send(channel, ...args)
channel
String 事件名称...args
any[] 传递的参数,和上节一样
目录准备,修改和删除都在这几个文件操作
my-electron-app/
├── package.json
├── main.js // 这个就是主进程
├── renderer.js // 这个就是渲染进程
└── index.html //web页面
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Electron演示</title>
</head>
<body>
Electron演示
<iframe src='./other.html'></iframe>
<script src="./renderer.js"></script>
</body>
</html>
renderer.js
const { ipcRenderer } = require("electron");
ipcRenderer.on("message", (event, arg) => {
console.log("主进程老哥,主动推消息了:", arg);
});
main.js
const { app, BrowserWindow, ipcMain } = require("electron");
function createWindow() {
const win = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
const contents = win.webContents;
contents.openDevTools(); //打开调试工具
win.loadFile("index.html");
contents.on("did-finish-load", () => {
//页面加载完成触发的回调函数
console.log("load");
contents.send("message", "我看到你加载完了,给你发个信息");
});
}
app.whenReady().then(createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
contents.sendToFrame(frameId, channel, ...args) 通过frameId给渲染进程中嵌入的webview发送消息
frameId
Integer | [number, number]channel
String...args
any[]
首先如何拿到框架的id?
第一种渲染进程主动调用方法去拿到id,然后调用取方法
console.log('My frameId is:', require('electron').webFrame.routingId) //然后你把这个传给主进程
第二种主进程通过监听的函数去拿,因为渲染进程发消息会触发主进程的事件,我们就可以通过event去拿
ipcMain.on('ping', (event) => {
console.info('Message came from frameId:', event.frameId)
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Electron演示</title>
</head>
<body>
Electron演示
<webview src='./other.html' webpreferences="nodeIntegration=true"></webview> //具体查api
<script src="./renderer.js"></script>
</body>
</html>
main.js
const { app, BrowserWindow, ipcMain } = require("electron");
let win;
function createWindow() {
win = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
nodeIntegration: true,
webviewTag: true, //需要设置webview来启用这个
},
});
const contents = win.webContents;
contents.openDevTools(); //打开调试工具
win.loadFile("index.html");
contents.on("did-finish-load", () => {
//页面加载完成触发的回调函数
console.log("load");
// contents.send("message", "我看到你加载完了,给你发个信息");
});
}
ipcMain.on("getFrameId", (event, arg) => {
console.log("收到了FrameId", arg); //收到了FrameId 1
console.log("event收到了FrameId", event.frameId); //event收到了FrameId 1
win.webContents.sendToFrame(
event.frameId,
"message",
"我看到你加载完了,给你发个信息"
);
});
app.whenReady().then(createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
other.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>其他页面</title>
</head>
<body>
<script>
const {
ipcRenderer,
webFrame
} = require("electron");
ipcRenderer.send("getFrameId", webFrame.routingId);
ipcRenderer.on("message", (event, arg) => {
console.log("(renderer2)主进程老哥,主动推消息了:", arg);
});
</script>
</body>
</html>
renderer.js
const { ipcRenderer, webFrame } = require("electron");
console.log("My frameId is:", webFrame.routingId);
ipcRenderer.on("message", (event, arg) => {
console.log("(renderer2)主进程老哥,主动推消息了:", arg);
});
结果
contents.postMessage(channel, message, [transfer]) 利用原生的webworker进行通讯
channel
Stringmessage
anytransfer
MessagePortMain[] (optional)
只写关键性代码,具体的代码参看最上面的改动,对照一下
main.js
contents.on("did-finish-load", () => {
const { port1, port2 } = new MessageChannelMain();
contents.postMessage("message", "我看到你加载完了,给你发个信息", [port1]);
port2.postMessage("再给你发个消息");
});
renderer.js
ipcRenderer.on("message", (event, arg) => {
const [port] = event.ports;
console.log(arg, event);
port.onmessage = (arg) => {
console.log(arg.data);
};
});
结果
-
我看到你加载完了,给你发个信息 Object
-
再给你发个消息
以上就是借助 webContent功能模块 主进程向渲染进程通信
渲染进程互相通信
ipcRenderer.sendTo(webContentsId, channel, ...args)
webContentsId
Number 渲染进程的idchannel
String...args
any[]
获取渲染进程的id
- 可以在创建窗口的时候保存每个窗口的id
- 或者创建一个主进程事件获取每个渲染进程的id
main.js
const { app, BrowserWindow, ipcMain } = require("electron");
let win;
let ids = {
"index.html": null,
};
function createWindow() {
win = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
webviewTag: true, //需要设置webview来启用这个
},
});
const contents = win.webContents;
contents.openDevTools(); //打开调试工具
win.loadFile("index.html");
ids["index.html"] = contents.id;
}
ipcMain.on("registerFrameId", (event, arg) => {
console.log(arg);
ids = Object.assign(ids, arg);
});
ipcMain.on("getFrameId", (event, arg) => {
event.returnValue = ids[arg];
});
app.whenReady().then(createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
renderer.js
const { ipcRenderer } = require("electron");
onload = () => {
const webview = document.querySelector("webview");
webview.addEventListener("did-finish-load", () => {
webview.openDevTools();
let otherId = ipcRenderer.sendSync("getFrameId", "other.html");
console.log(otherId);
ipcRenderer.sendTo(otherId, "webview", "other老弟,喝一口");
});
ipcRenderer.on("webview", (event, arg) => {
console.log("来自other.html消息:", arg);
});
};
other.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>其他页面</title>
</head>
<body>
<script>
onload = () => {
const {
ipcRenderer,
remote //从remote模块获取到窗体的唯一id
} = require("electron");
// let webContent = webContents.getFocusedWebContents()
const webContent = remote.getCurrentWebContents();
console.log(webContent.id)
ipcRenderer.send("registerFrameId", {
'other.html': webContent.id
});
let indexId = ipcRenderer.sendSync('getFrameId', 'index.html')
ipcRenderer.sendTo(indexId, "webview", "index老哥,给你发消息了");
ipcRenderer.on("webview", (event, arg) => {
document.write("来自html.html消息:", arg)
});
}
</script>
</body>
</html>
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Electron演示</title>
</head>
<body>
Electron演示
<webview src='./other.html' webpreferences="nodeIntegration=true" id="webview"></webview>
<script src="./renderer.js"></script>
</body>
</html>
结果
ipcRenderer.sendToHost(channel, ...args)
channel
String...args
any[]
就像 ipcRenderer.send
,不同的是消息会被发送到 host 页面上的 <webview>
元素,而不是主进程
需要用到webview的一个事件监听 'ipc-message' 监听发布的消息
具体改动这个地方
other.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>其他页面</title>
</head>
<body>
asdada
<script>
const {
ipcRenderer,
} = require("electron");
ipcRenderer.on('ping', (event, arg) => {
console.log("来自主页面的回话", arg)
ipcRenderer.sendToHost('message', '小哥我给你发信息了')
})
</script>
</body>
</html>
renderer.js
onload = () => {
const webview = document.querySelector("webview");
webview.addEventListener("ipc-message", (event) => {
console.log("来自webview的回话:", event);
});
webview.addEventListener("did-finish-load", () => {
webview.openDevTools();
webview.send("ping", "理我一下");
});
};
结果
如果觉得我的文章还可以,点个赞或者关注一下下,还有精彩的故事等着你哦,还可以云撸猫
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!