簡體   English   中英

Electron 輔助 window 未收到 IPC 消息

[英]Electron secondary window not receiving IPC messages

在我的 typescript 連接到由我的應用程序運行的 HTML 中,我正在為我的設置創建一個新的 window。 據我所知,新的 window 一旦打開,預加載的腳本也會被加載到它上,但是 window 沒有從主腳本接收 IPC 消息。

這是預加載的腳本:

const { contextBridge, ipcRenderer } = require("electron");

console.log("preloaded!");

contextBridge.exposeInMainWorld("api", {
  send: (channel, data) => {
    let validChannels = ["toMain", "select-dirs", "toSettings", "fromSettings"];
    if (validChannels.includes(channel)) {
      ipcRenderer.send(channel, data);
    }
  },
  receive: (channel, func) => {
    let validChannels = ["fromMain", "toSettings", "fromSettings"];
    if (validChannels.includes(channel)) {
      ipcRenderer.on(channel, (event, ...args) => func(...args));
    }
  },
});

這是我附加到第二個窗口的 HTML 的 typescript 文件。

(<any>window).api.receive("toSettings", (data: any) => {
  console.log(data);
})

var closeButton: HTMLButtonElement;

var settings = "";
var settignsDir = "";

document.onreadystatechange = () => {
  if (document.readyState == "interactive") {
    (<any>window).api.send("fromSettings", "ready")
    closeButton = <HTMLButtonElement>document.getElementById("closeButton");

    closeButton.addEventListener("click", () => {
      (<any>window).api.send("toMain", "refresh");
      self.close();
    });
  }
};

我為我的渲染器使用相同的預加載腳本並使用相同的接收代碼,它工作得很好。 並且從第二個窗口的 typescript 中,我可以正確地將 IPC 消息發送到主進程。 但是我在第二個 window 上收不到任何消息。 我想我需要通過window.open()中的 features 數組將文件直接重新加載到第二個 window 。 哦,這是打開設置 window 的代碼。

window.open(
          "./html/settings.html",
          "_blank",
          "top=200,left=600,frame=false,nodeIntegration=no"
        );

根據 Electron 文檔,您還可以在第三個字符串中包含一個預加載,但我不知道如何,因為文檔沒有示例並且我在任何地方都找不到。

回應 Kdau:

這是請求的代碼:

(<any>window).api.receive("fromSettings", (data: any) => {
  (<any>window).api.send("toSettings", "WHAT!");
})

我主要是用它來查看你所說的設置或子 window 是否正在接收消息。 如果你能澄清你對子 window 的地址是什么意思,因為我認為預加載腳本應該自動解析,“好的,所以這個通道需要 go 到這個接收器”。

我想指出,在您包含的代碼片段中返回此錯誤: Argument of type '({ url }: HandlerDetails) => { frame: boolean; web首選項:{節點集成:boolean; 預載:字符串; }; } | undefined' 不能分配給類型為 '(details: HandlerDetails) => { action: "deny"; } | { 動作:“允許”; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | 不明確的; }'。 類型'{框架:boolean; web首選項:{節點集成:boolean; 預載:字符串; }; } | undefined' 不可分配給類型 '{ action: "deny"; } | { 動作:“允許”; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | 不明確的; }'。 類型 'undefined' 不能分配給類型 '{ action: "deny"; } | { 動作:“允許”; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | 不明確的; }'。

我不知道該怎么辦。

雖然您可以在第三個參數中傳遞預加載,但更靈活和可靠的方法是使用setWindowOpenHandler 因此,在構建您的主 window 之后(假設變量是mainWindow ):

mainWindow.webContents.setWindowOpenHandler(({ url }) => {
  if (url === './html/settings.html') {
    return {
      action: 'allow',
      overrideBrowserWindowOptions: {
        frame: false,
        webPreferences: {
          nodeIntegration: false,
          preload: 'my-child-window-preload-script.js'
        }
      }
    }
  }
})

但是,大多數(全部??)選項無論如何都是從父 window 繼承的,我想您的preload已被繼承,這就是為什么您可以從子 window 發送消息的原因。

至於未在子 window 中接收消息,您的代碼不會將消息發送到該窗口的webContents 發送到主窗口的webContents將不起作用。 不幸的是,Electron 中的 IPC 不是一個廣播系統,每個進程都接收僅按通道過濾的每條消息。 渠道功能位於基於流程的定位之上。 每個渲染進程只能向主進程發送消息,並且主進程在發送時必須一次處理一個特定的渲染進程。

因此,要在兩個渲染進程之間進行通信,請將主進程用作中繼。 在主進程中,要獲取通過 window.open 打開的webContentswindow.open ,您可以偵聽來自該進程的消息(例如您在加載后立即發送的消息)和/或調用webContents.getAllWebContents()並遍歷以找到正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM