簡體   English   中英

將一些初始數據傳遞到新窗口的正確方法是什么?

[英]What's the right way to pass some initial data to a new window?

我只是在學習 Electron,我正在嘗試打開一個文件並在新窗口中顯示它。 我在初始(根)窗口中單擊一個按鈕,然后打開一個“打開文件”對話框,從中可以獲取文件路徑。 我想然后打開該文件,創建一個窗口,並將文件內容傳遞到新窗口。 我的問題是在窗口准備好時將帶有文件內容的字符串放入回調函數中; 我什至可能嗎? 我的 main.js 代碼:

 function createWindow (templateFile, initialData) { console.log("Creating window....") newWindow = new BrowserWindow({width: 800, height: 600, webPreferences: {preload: path.join(__dirname, 'preload.js'), nodeIntegration: true} }) newWindow.loadFile(templateFile) newWindow.webContents.openDevTools() //This is what doesn't work; I want to take the initialData argument to the createWindow function, //and get it into the 'did-finish-load' callback function newWindow.webContents.on('did-finish-load', (event, initialData) => { windowsArray[newWindow.webContents.id] = newWindow console.log(initialData) newWindow.webContents.send("initialDataLoad", initialData) }) newWindow.on('closed', function () {newWindow.object = null}) } ipcMain.on("new-sheet", (event, gameDefinitionFile) => { console.log("Loading " + gameDefinitionFile) let gameDefContents fs.readFile(gameDefinitionFile, 'ascii', (err, gameDefContents) => {}) createWindow("defaultSheet.html", gameDefContents) })

我已經讀到您可以在 webContents 對象上創建一個新屬性,然后從渲染器進程中引用它,但這聽起來不像是真正正確的做法。 那么,我應該怎么做呢?

完整代碼在https://gitlab.com/sjbrown8/osiris

我不確定我是否完全理解您需要做什么,但是您可以使用 准備顯示事件在第一次顯示窗口之前將數據發送到新窗口。

如果數據被用於填充現有的頁面元素,這可能是最有意義的——盡管我猜你沒有理由不能用新數據炸掉頁面上的任何東西——這只是另一種渲染。

在加載頁面時,如果窗口尚未顯示,則當渲染器進程第一次渲染頁面時,將發出 ready-to-show 事件。

主程序

mainWindow.once('ready-to-show', () => {
    Menu.setApplicationMenu(basicMenu);

    let data = "some data that have have read from disk and want to send to this new window"
    mainWindow.webContents.send('message', { "event": "data dump", data: data});
    mainWindow.show()
})

渲染器

ipcRenderer.on('message', (event, arg) => {
  switch (arg.event) {
      case "data dump":

       // just a <textArea> but you could do anything with the data.
      $("#dump").text(arg.data);
      break;
  }
});

webContents方式應該以簡單的方式解決您的問題。 這很簡單:您提前創建並收集窗口需要的所有數據,然后用它生成窗口。

webContents方式有一些限制,因為您在main上創建的webContents對象被序列化並發送到render - 這意味着,兩個進程都有對象的獨立版本:

  1. 您在數據的渲染過程版本上應用於對象的更改將不會反映到 main 中(反之亦然)
  2. 您不能傳遞函數(例如使用它在渲染過程中從 main 調用函數)

但是使用簡單的初始化數據:它很容易理解。

編輯:

當然,發送方法需要一個通道名稱和一個可選的對象,即您要發送的數據。 你可以這樣寫一個函數:

sendPersonData(personData) => {
   webContents.send('person-data-updated', personData);
);

或者,如果您想要一個采用回調進行靈活發送的函數:

updatePersonData(personData, senderCallback) => {
   updatedPersonData = functionToUpdatePersonData(personData);
   senderCallback(personData);
}

// and use that like so:
updatePersonData({name: 'John Doe'}, sendPersonData);

監聽渲染器有一大缺點。 渲染器只獲取一次數據,如果您允許刷新瀏覽器窗口 (CTRL+R),則瀏覽器窗口將丟失數據並且不會再次初始化。

在我看來,讓渲染器像這樣提取初始數據更安全:

渲染器

let initialData;
ipcRenderer.invoke('fetch-initial-data')
  .then((data) => initialData = data);

主要的

const initialData = createItSomehow();
ipcMain.handle('fetch-initial-data', () => initialData);

這樣,當我們刷新屏幕時,數據將始終從“后端”獲取。 請注意,它在渲染器上是異步的。

暫無
暫無

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

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