个性化阅读
专注于IT技术分析

如何在Electron Framework中将信息从一个窗口发送到另一个窗口

本文概述

许多桌面应用程序提供操纵和自定义功能。这些功能通常(并非总是)位于与原始应用程序不同的窗口中, 因此在使用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样式(背景色为黑色和文本色为白色)的对象, 并将输入的文本发送到第二个窗口。在第二个窗口中, 将处理该对象并将其显示在视图中:

Electron将数据从一个窗口发送到另一个窗口

请注意, 你可以遵循相同的过程, 但是要反向进行(从第二个窗口到第一个窗口)。

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何在Electron Framework中将信息从一个窗口发送到另一个窗口

评论 抢沙发

评论前必须登录!