本文概述
许多桌面应用程序提供操纵和自定义功能。这些功能通常(并非总是)位于与原始应用程序不同的窗口中, 因此在使用Electron时, 你将需要学习如何将信息从一个窗口共享到另一个窗口。
在本文中, 我们将向你展示如何使用Electron的IPCMain和IPCRenderer模块来完成此简单任务。
注意
该过程可以双向进行, 因此你可以按照以下步骤将信息从第一个窗口发送到第二个窗口, 反之亦然。
1.配置2个Windows(可选)
如果主进程中已经有2个Windows实例, 则跳过此步骤。在我们的示例中, 我们将有2个带有变量mainWindow和secondWindow的窗口。这些窗口是在主进程中创建的(来自main.js), 它们将同时显示, 因此你可以根据需要更改其行为。重要的是你有2个Windows, 并且可以通过变量访问它们:
// Keep a global reference of the windows object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
let secondWindow;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({ width: 800, height: 600 });
secondWindow = new BrowserWindow({ width: 800, height: 600 });
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true
}))
// and load the second window.
secondWindow.loadURL(url.format({
pathname: path.join(__dirname, 'otherfile.html'), protocol: 'file:', slashes: true
}))
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
secondWindow = null;
})
}
这两个窗口都加载2个不同的HTML文件。
2.在主进程中添加侦听器以在Windows之间共享数据
现在, 你已经拥有两个将相互通信的窗口, 你可以在主流程中创建端点, 作为它们之间的桥梁。使用Electron的ipcMain模块, 可以在有权访问2个窗口的主窗口(后台进程)中添加”事件侦听器”, 然后可以使用ipcRenderer从第一个窗口的视图触发此事件。
以下代码添加了一个事件侦听器(在main.js中), 该事件侦听器将在第一个窗口的视图中触发” request-update-label-in-second-window”(日期名称)事件时执行。在回调内部, 就像在可访问2个窗口的main.js文件中一样, 你可以访问要在其中发送信息的窗口的webContents属性。 webContents是一个EventEmitter。它负责呈现和控制网页, 并且是BrowserWindow对象的属性。使用send方法, 可以在第二个窗口的渲染器过程中触发一个事件(即action-update-label):
const { ipcMain } = require('electron');
// Attach event listener to event that requests to update something in the second window
// from the first window
ipcMain.on('request-update-label-in-second-window', (event, arg) => {
// Request to update the label in the renderer process of the second window
// We'll send the same data that was sent to the main process
// Note: you can obviously send the
secondWindow.webContents.send('action-update-label', arg);
});
现在, 我们在后台建立了桥梁。接下来, 你需要在第二个窗口中构建桥的入口点。
3.在第二个窗口的视图中添加侦听器以接收数据
逻辑的其余部分非常明显, 因为你从主流程中触发了事件action-update-label, 所以当触发此事件时, 你需要在第二个窗口中执行某些操作。在第二个窗口的渲染器进程(otherfile.html)中, 使用以下代码继续使用ipcRenderer模块添加事件侦听器:
// Require ipcRenderer
const { ipcRenderer } = require('electron');
// When the action-update-label event is triggered (from the main process)
// Do something in the view
ipcRenderer.on('action-update-label', (event, arg) => {
// Update the second interface or whatever you need to do
// for example show an alert ...
alert("Hello, you did something in the first window !");
// arg contains the data sent from the first view
console.log(arg);
});
现在, 当从主流程中的第一个窗口触发事件”第二窗口中的请求更新标签”时, 主流程将触发动作更新标签事件, 该事件将执行你需要的操作。
4.触发分享事件
最后一步, 你只需要在第一个窗口(在渲染器进程中)触发” request-update-label-in-second-window”:
const { ipcRenderer } = require('electron');
// Some data that will be sent to the main process
// Feel free to modify the object as you wish !
let Data = {
message: "Hello World !"
};
// Trigger the event listener action to this event in the renderer process and send the data
ipcRenderer.send('request-update-label-in-second-window', Data);
这将遵循上述逻辑, 将带有属性消息的Data对象发送到第二个视图中的渲染器进程。
例子
以下基于3个文件的示例说明了一个简单应用程序中提到的步骤:
main.js
const electron = require('electron');
const path = require('path');
const { ipcMain } = require('electron');
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
const url = require('url')
// Keep a global reference of the windows object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
let secondWindow;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({ width: 800, height: 600 });
secondWindow = new BrowserWindow({ width: 800, height: 600 });
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true
}))
// and load the second window.
secondWindow.loadURL(url.format({
pathname: path.join(__dirname, 'otherfile.html'), protocol: 'file:', slashes: true
}))
// Attach event listener to event that requests to update something in the second window
// from the first window
ipcMain.on('request-update-label-in-second-window', (event, arg) => {
// Request to update the label in the renderer process of the second window
secondWindow.webContents.send('action-update-label', arg);
});
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
secondWindow = null;
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Electron Application</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=1">
</head>
<body>
<div id="app">
Hello First Window
<br />
<input type="text" id="field" value="This String Will be Sent to the second Window" />
<input type="button" id="btn" value="Update Label in Second Window with Text" />
</div>
<script>
const { ipcRenderer } = require('electron');
document.getElementById("btn").addEventListener("click", () => {
// Some data that will be sent to the main process
let Data = {
message: document.getElementById("field").value, backgroundColor: "black", color: 'white'
};
// Trigger the event listener action to this event in the renderer process and send the data
ipcRenderer.send('request-update-label-in-second-window', Data);
}, false);
</script>
</body>
</html>
otherfile.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Electron Second Window</title>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=1">
</head>
<body>
<div id="app">
Hello Second Window
<br />
<span id="label">Hello This Label Will be updated </span>
</div>
<script>
const { ipcRenderer } = require('electron');
ipcRenderer.on('action-update-label', (event, arg) => {
// Update the second window label content with the data sent from
// the first window :) !
let label = document.getElementById("label");
label.innerHTML = arg.message;
label.style.color = arg.color;
label.style.backgroundColor = arg.backgroundColor;
});
</script>
</body>
</html>
在Electron中执行前面的代码, 将显示2个窗口。在第一个窗口中, 你会找到一个简单的文本输入和一个按钮, 单击该按钮后, 它将向你发送具有CSS样式(背景色为黑色和文本色为白色)的对象, 并将输入的文本发送到第二个窗口。在第二个窗口中, 将处理该对象并将其显示在视图中:
请注意, 你可以遵循相同的过程, 但是要反向进行(从第二个窗口到第一个窗口)。
编码愉快!
评论前必须登录!
注册