Electron:如何跨多个文件共享 BrowserWindow 实例?

Electron: How to share BrowserWindow instance across multiple files?

我想要一个 js 文件,比方说 window.js,它负责创建和导出 BrowserWindow 的唯一实例,这样我就可以在多个 js 文件中重用这个实例。

直到现在我试过这个:

    const { app, BrowserWindow } = require("electron");
    
    let window = null;
   
    const createWindow = () => {
      if (window) return;
      window = new BrowserWindow({
      minWidth: 820,
      minHeight: 620,
      width: 820,
      height: 620,
      resizable: false,
      webPreferences: {
        preload: path.join(__dirname, "preload.js"),
        enableRemoteModule: true,
      },
     });
     window.removeMenu();
    };

app.whenReady().then(() => {
  createWindow();
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
      //   showRecorderWindow();
    }
  });
});

module.exports = {
  window
}

然而,当我需要 window 时使用: const { window } = require("./window.js"); window 变量始终为空。有什么办法可以实现吗?

当您使用 module.exports = <object> 时,您创建的是对象的副本,没有 link 回到原始对象。在您的代码中,在 app.whenReady() 部分中创建 window 之前,module.exports 部分是 运行。这是因为 app.whenReady() 部分中的函数是 运行 异步的。所以此时 module.exports = { window } 是 运行,window 仍然等于 null。要解决此问题,您需要在 createWindow() 之后将 module.exports 移动到 app.whenReady() 中,或者为了修复范围,将其移动到 createWindow() 中(我还更正了缩进):

const { app, BrowserWindow } = require("electron");

const createWindow = () => {
  if (window) return;
  const window = new BrowserWindow({
    minWidth: 820,
    minHeight: 620,
    width: 820,
    height: 620,
    resizable: false,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      enableRemoteModule: true,
    },
  });
  window.removeMenu();
  module.exports = {
    window
  }
};

app.whenReady().then(() => {
  createWindow(); 
  app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
      //   showRecorderWindow();
    }
  });
});

现在,当您需要 windows.js 时,它将 return 最新的 window 对象。只需确保在应用准备就绪后执行 const { window } = require("./window.js");

// file2.js

const { app, BrowserWindow } = require("electron");

let window = null;

app.whenReady().then(() => {
  app.on("activate", () => {
    if (window == null) {
      { window } = require("./window.js");
    }
  });
});

请注意,您不能多次 require("./window.js") 来获取最新的 window,因为 node.js 会在您需要时保留一份 window.js。您可能还想查看 inter-process 通信:https://www.electronjs.org/docs/latest/tutorial/ipc

使用“setter”和“getter”将解决您的问题。

您的 main.js 文件应该 require 您的 window.js 模块和 create() window.

如果任何其他 Javascript 文件需要访问 window 实例,那么在该文件中您可以 require window.js 模块,然后只需调用get() 函数。


在您的 main.js(主线程)文件中:

  1. require window.js 文件,其中包含 createget 函数。
  2. 声明 window 变量,使其不被垃圾回收。
  3. electronApp.on('ready', ...) 上将创建的 window 实例分配给 window 变量。
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;

const nodePath = require("path");

const appWindow = require(nodePath.join(__dirname, 'window'));

// Prevent garbage collection
let window;

electronApp.on('ready', () => {
    window = appWindow.create();
});

electronApp.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        electronApp.quit();
    }
});

electronApp.on('activate', () => {
    if (electronBrowserWindow.getAllWindows().length === 0) {
        appWindow.create();
    }
});

在您的 window.js(主线程)文件中:

  1. 创建 2 个函数 - 一个到 create window,一个到 get window 实例。
  2. 导出这两个函数以便在别处使用。
const electronBrowserWindow = require('electron').BrowserWindow;

const nodePath = require('path');

let window; // Top level scope within the module

function create() {
    window = new electronBrowserWindow({
        x: 0,
        y: 0,
        width: 800,
        height: 600,
        show: false,
        webPreferences: {
            nodeIntegration: false,
            contextIsolation: true,
            preload: nodePath.join(__dirname, 'preload.js')
        }
    });

    window.loadFile('index.html')
        .then(() => { window.show(); });

    return window; // Return the instance of the window
}

function get() {
    return window; // Return the instance of the window
}

// Export the publicly available functions.
module.exports = {create, get};

最后,当你需要在another.js(主线程)文件中引用window的实例时:

  1. require window.js 文件。
  2. 调用get()函数。
const nodePath = require('path');

const appWindow = require(nodePath.join(__dirname, 'window'));

let window = appWindow.get();

当您需要使用特定 window 作为子 window 或对话框的父级时,这非常方便。