📜  如何在 Electron JS 应用程序的多个窗口之间切换?

📅  最后修改于: 2022-05-13 01:56:41.400000             🧑  作者: Mango

如何在 Electron JS 应用程序的多个窗口之间切换?

如果您有 Web 应用程序开发的先验知识并考虑开始构建桌面应用程序,那么您来对地方了。

ElectronJS是一个开源框架,可帮助使用简单的 HTML、CSS 和 JavaScript 开发跨平台桌面应用程序。即使您想使用 Angular 或 React 开发应用程序并尝试构建它的桌面版本,Electron JS 也为您提供相同的支持。 Electron 使用无头 Chromium 浏览器,它通过 Electron 自己的 API 提供对 Node JS API 的访问。

在任何 Web 应用程序中,当我们单击某些链接时,有时会在浏览器中打开一个包含新内容的新选项卡。此外,我们认为您在桌面应用程序的情况下观察到相同的行为。当我们单击任何桌面应用程序中的某个按钮时,它会在前一个窗口的顶部打开一个新窗口,并且在我们关闭顶部窗口(或新窗口)之前,主窗口将无法工作。 Electron 提供了基于按钮单击或单击任何链接打开多个窗口的功能。

为了便于理解,假设您开发了一个应用程序,并且您想在另一个窗口中打开“设置”页面。本教程将演示如何使用 Electron JS 在新窗口中打开设置页面。

我们假设您熟悉电子应用程序的基本设置(如果不熟悉,请通过创建基本电子应用程序)。需要在系统中安装 Node 和 npm 才能运行 Electron 应用程序。

项目结构:让我们从项目的基本结构开始,如下所示。

项目结构

  • node_modules :这包含在您执行npm init -y时创建的节点 JS 包
  • app.js :这是主要的 Electron JS 文件,我们在其中指定应用程序窗口配置
  • index.html :这是主要的 HTML 文件(将其视为我们应用程序的主页)
  • package-lock.json :当我们修改 node_modules 或 package.json 中的某些内容时,该文件已由 npm 自动生成
  • package.json :这个文件由 npm 生成,它包含我们项目的附加依赖项(如电子)和一些其他设置
  • settings.html :这是设置 HTML 文件(将显示在设置窗口中)

包.json

{
  "name": "electron-app",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "start": "electron ."
  },
  "author": "Sandip",
  "license": "ISC",
  "dependencies": {
    "electron": "^12.0.2"
  }
}

将主脚本文件 ( main.js ) 从 Create Basic Electron Application 复制到我们的app.js ,它作为我们应用程序的主进程。

index.html中编写简单的 HTML 代码(就好像它是你的第一个窗口或主窗口一样)如下

index.html


    
        First Window
    
    
        
            

              Hello : This is first window             

            
                        
    


app.js
const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");
  
let mainWindow;
  
// Function to create independent window or main window
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    // Make sure to add webPreferences with
    // nodeIntegration and contextIsolation
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
    show: false,
  });
  
  // Main window loads index.html file
  mainWindow.loadFile("index.html");
  
  // To maximize the window
  mainWindow.maximize();
  mainWindow.show();
}
  
// Function to create child window of parent one
function createChildWindow() {
  childWindow = new BrowserWindow({
    width: 1000,
    height: 700,
    modal: true,
    show: false,
    parent: mainWindow, // Make sure to add parent window here
  
    // Make sure to add webPreferences with below configuration
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true,
    },
  });
  
  // Child window loads settings.html file
  childWindow.loadFile("settings.html");
  
  childWindow.once("ready-to-show", () => {
    childWindow.show();
  });
}
  
ipcMain.on("openChildWindow", (event, arg) => {
  createChildWindow();
});
  
app.whenReady().then(() => {
  createWindow();
  
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});
  
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});


Javascript
const ipc = window.require('electron').ipcRenderer;
  
// Function that will be called on click 
// event of "Go to settings window" button
function goToSettingsWindow(){
  
    // Make sure to do ipc.send('some String'), 
    // where 'some String' must be same with 
    // the first parameter of ipcMain.on() in app.js 
    ipc.send('openChildWindow');  
}


settings.html



    Settings


    
        

          Hello : This is Settings window         

             


Javascript
const remote = window.require("electron").remote;
  
function goToFirstWindow() {
  //code for some other action to be performed
  
  //Code to close the window after doing other actions
  remote.getCurrentWindow().close();
}


输出:

初始窗口

app.js:我们打算在您单击“转到设置窗口”按钮时打开一个新的设置窗口。让我们检查一下app.js文件中要进行的必要更改。

应用程序.js

const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");
  
let mainWindow;
  
// Function to create independent window or main window
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    // Make sure to add webPreferences with
    // nodeIntegration and contextIsolation
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
    },
    show: false,
  });
  
  // Main window loads index.html file
  mainWindow.loadFile("index.html");
  
  // To maximize the window
  mainWindow.maximize();
  mainWindow.show();
}
  
// Function to create child window of parent one
function createChildWindow() {
  childWindow = new BrowserWindow({
    width: 1000,
    height: 700,
    modal: true,
    show: false,
    parent: mainWindow, // Make sure to add parent window here
  
    // Make sure to add webPreferences with below configuration
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false,
      enableRemoteModule: true,
    },
  });
  
  // Child window loads settings.html file
  childWindow.loadFile("settings.html");
  
  childWindow.once("ready-to-show", () => {
    childWindow.show();
  });
}
  
ipcMain.on("openChildWindow", (event, arg) => {
  createChildWindow();
});
  
app.whenReady().then(() => {
  createWindow();
  
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});
  
app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

  • 电子模块导入ipcMain
  • 如上添加createChildWindow()方法,基本上包含了子窗口(即设置窗口)的所有设置和配置
  • 如果你这样做了, childWindow.parent = mainWindow同上,那么在子窗口关闭之前,父窗口将被禁用。
  • 如果省略childWindow.parent ,则会打开一个新窗口,但子窗口和父窗口之间不会有任何联系。
  • 包括ipcMain.on('openChildWindow', (event, arg) => { createChildWindow(); } );基本上调用 createChildWindow() 方法,同时我们通过 ipcRenderer 在按钮单击时发送“ openChildWindow”事件。
  • 将具有上述所有键值的webPreferences属性添加到mainWindow对象,这使我们能够使用 Electron 的远程 ipcRenderer 来处理子窗口。

让我们在index.html中添加以下脚本

Javascript

const ipc = window.require('electron').ipcRenderer;
  
// Function that will be called on click 
// event of "Go to settings window" button
function goToSettingsWindow(){
  
    // Make sure to do ipc.send('some String'), 
    // where 'some String' must be same with 
    // the first parameter of ipcMain.on() in app.js 
    ipc.send('openChildWindow');  
}

这里我们使用电子模块的ipcRenderer发送事件' openChildWindow '并且 ipcMain (在app.js中指定)正在监听这个事件并调用createChildWindow()方法。

让我们创建一个settings.html文件,该文件将在主窗口中单击按钮(“转到设置窗口”按钮)时显示在子窗口中。

设置.html




    Settings


    
        

          Hello : This is Settings window         

             

输出:在添加“转到主窗口”功能之前,让我们检查打开设置窗口的输出

让我们在settings.html中添加以下脚本来关闭设置窗口并返回主窗口(如果通过单击窗口关闭(右上角的X按钮)关闭窗口,也可以,但有时我们需要在关闭窗口之前执行一些其他操作,例如数据库更新或配置更新,为此,您需要在单击按钮时关闭窗口)

Javascript

const remote = window.require("electron").remote;
  
function goToFirstWindow() {
  //code for some other action to be performed
  
  //Code to close the window after doing other actions
  remote.getCurrentWindow().close();
}

在这里,我们正在访问电子模块的远程对象以获取 currentWindow 对象。

输出:让我们检查一下我们的最终应用程序。