簡體   English   中英

Electron React - 嘗試導入 ipcRenderer - 未調用 preload.js

[英]Electron with React- trying to import ipcRenderer - preload.js is not being called

我正在嘗試使用 ipc 將頁面數據發送到 electron 當我運行 elctron 應用程序時,window.ipcRenderer 只是未定義(在 electron 應用程序內)

這是代碼

主.js:

const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')

const mainWindow = new BrowserWindow({
    width: 1080,
    height: 920,
    fullscreenable: false,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

.

ipcMain.on("play-vlc-magnet", (event, magnet) => {
  //run_script("webtorrent --vlc " + magnet)
  console.log("recevied:", magnet)
})

preload.js(console.log 不會出現在控制台中):

console.log("running preload")
window.ipcRenderer = require('electron').ipcRenderer;

在 react compon.net 中被調用的行:

  window.ipcRenderer.send("play-vlc-magnet", r.data)

React 中的元素(寫着“ipc 不存在”)

 <p>{(typeof window.ipcRenderer !== "undefined") ? "ipc renderer exists" : "ipc doesn't exist"</p>

理解和實現一個有效的preload.js腳本可能很困難。

過去,我發現最好反復閱讀以下要點,直到您了解主進程和渲染進程之間的區別、使用preload.js腳本的內容和原因以及如何實現工作preload.js並與之交互腳本。 在那之后,天空是極限。

preload.js腳本中實現具體功能是常見的做法(如 Electron 文檔所示)。 雖然這種方法沒有任何問題,但我相信在最初嘗試理解和使用這種方法時很容易混淆。

相反,我個人的方法是僅使用一個preload.js腳本並通過僅使用列入白名單的通道名稱對其進行編碼以傳輸數據。 這使我能夠:

  1. 我創建的所有 windows 只使用一個preload.js腳本。
  2. 在一個地方定義所有列入白名單的頻道名稱的主列表。
  3. 有一個小的preload.js腳本文件大小,沒有具體的實現。
  4. 分離關注點並將具體 function 的實現放回到它們適當的(主進程和渲染進程)域中。

在下面的代碼片段中,我展示了程序員在 Electron 文檔中展示的“常用”方法和我常用的替代方法。 您可以決定哪個最適合您的理解和編碼風格。


讓我們從一個有效的preload.js腳本開始,這是阻止您在渲染進程和主進程之間進行通信的部分。

preload.js (主進程)

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

contextBridge.exposeInMainWorld(
    'electronAPI', {
        playVlcMagnet: (data) => ipcRenderer.send('play-vlc-magnet', data)
    }
)

作為上述“通用” preload.js腳本的替代方案,以下是我個人的偏好。

preload-alt.js (主進程)

// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [
            'play-vlc-magnet' // Channel name
        ],
        // From main to render.
        'receive': [],
        // From render to main and back again.
        'sendReceive': []
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

以及如何使用它。

/**
 * Render --> Main
 * ---------------
 * Render:  window.ipcRender.send('channel', data); // Data is optional.
 * Main:    ipcMain.on('channel', (event, data) => { methodName(data); })
 *
 * Main --> Render
 * ---------------
 * Main:    windowName.webContents.send('channel', data); // Data is optional.
 * Render:  window.ipcRender.receive('channel', (data) => { methodName(data); });
 *
 * Render --> Main (Value) --> Render
 * ----------------------------------
 * Render:  window.ipcRender.invoke('channel', data).then((result) => { methodName(result); });
 * Main:    ipcMain.handle('channel', (event, data) => { return someMethod(data); });
 *
 * Render --> Main (Promise) --> Render
 * ------------------------------------
 * Render:  window.ipcRender.invoke('channel', data).then((result) => { methodName(result); });
 * Main:    ipcMain.handle('channel', async (event, data) => {
 *              return await promiseName(data)
 *                  .then(() => { return result; })
 *          });
 */

接下來,是您似乎已正確實施的main.js文件。

main.js (主進程)

const app = require('electron').app;
const browserWindow = require('electron').BrowserWindow;
const ipcMain = require('electron').ipcMain;

const path = require('path');

let window;

function createWindow() {
    const window = new browserWindow({
        width: 1080,
        height: 920,
        fullscreenable: false,
        show: false,
        webPreferences: {
            nodeIntegration: false, // Default is false
            contextIsolation: true, // Default is true
            preload: path.join(__dirname, 'preload.js')  // Use of preload.js
            // preload: path.join(__dirname, 'preload-alt.js')  // Use of preload-alt.js
        }
    });

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

    return window;
}

app.on('ready', () => {
    window = createWindow();
});

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

app.on('activate', () => {
    if (browserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

// ---

ipcMain.on("play-vlc-magnet", (event, magnet) => {
    // run_script("webtorrent --vlc " + magnet)
    console.log("received: ", magnet)
})

最后,你的index.html文件,我沒有它的代碼,但你會明白的。

index.html (渲染進程)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Electron Test</title>
    </head>

    <body>
        <input type="button" id="button" value="Play VLC Magnet">
    </body>

    <script>
        let data = 'This is my data';

        document.getElementById('button').addEventListener('click', () => {
            window.electronAPI.playVlcMagnet(data); // Use of preload.js
            // window.ipcRender.send('play-vlc-magnet', data); // Use of preload-alt.js
        })
    </script>
</html>

暫無
暫無

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

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