Preload.js 需要问题

1 javascript require preload electron

最近我开始使用 Electron 框架练习 javascript,但我遇到了 preload.js 功能的问题。也许我不明白如何使用它,但我不能要求一些电子常数,因为它返回未定义

\n

我的 preload2.js:

\n
const { BrowserWindow } = require("electron");\nconsole.log(BrowserWindow);\n
Run Code Online (Sandbox Code Playgroud)\n

在我的窗口控制台中它返回

\n
Undefined\n
Run Code Online (Sandbox Code Playgroud)\n

我排除了问题可能是我的预加载未正确执行,但可能是:

\n

我的 main.js:

\n
const { app, BrowserWindow } = require('electron');\n\nfunction createWindow() {\n    console.log(app.getAppPath());\n    const win = new BrowserWindow({\n        width: 1000,\n        height: 600,\n        //Web preferences pu\xc3\xb2 utilizzare il preload.js \n        webPreferences: {\n            preload: app.getAppPath() + "\\\\preload2.js",\n        }\n    });\n    win.loadFile('index.html');\n\n}\n\n\n\napp.whenReady().then(createWindow);\n\n\n\napp.on('window-all-closed', () => {\n    if (process.platform !== 'darwin') {\n        app.quit()\n    }\n})\n
Run Code Online (Sandbox Code Playgroud)\n

请帮助我,我快失去理智了

\n

mid*_*ing 5

preload.js如果没有结构良好的基本示例,很难掌握Electron 脚本的正确使用。互联网上的许多示例将预加载脚本的主要功能(即管理主线程和渲染线程之间的通信通道)与这些通道的实现相结合。

为了进一步了解您的知识,请仔细阅读 Electron 的进程模型上下文隔离进程间通信页面。

一旦您阅读了这些页面(但不一定理解它们),让我们开始将它们缝合在一起,以便它们作为一个整体工作。


如前所述,preload.js脚本的目的是在主线程和渲染线程之间进行通信。如果向预加载脚本添加大量函数,预加载脚本很快就会变得不堪重负。

作为一种替代方法,我使用我的(唯一的)preload.js脚本来管理 IPC(按通道名称)。这意味着我在主线程和渲染线程之间传输或接收的特定白名单通道名称。任何不在白名单中的通道名称都将被拒绝通过。您还可以在发送通道名称时发送数据,以便另一端可以接收数据。

好吧,我们看一下preload.js文件。

preload.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': [
            'message:fromRender'
        ],
        // From main to render.
        'receive': [
            'message:toRender'
        ],
        // 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);
            }
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,您将看到通道名称message:fromRendermessage:toRender已添加到白名单中。

注意:诸如此类的对象BrowserWindow无法通过 IPC 发送,因为它们不可序列化。有关详细信息,请参阅对象序列化。


现在,在您的main.js文件中,除了预加载脚本的路径之外,一切看起来都很好。让我们改变这一点。

main.js(主线程)

const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

const nodePath = require("path");

let win;

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

    win.loadFile('index.html')
        .then(() => { win.show(); })
        // Send message to (win) render thread
        .then(() => { win.webContents.send('message:toRender', 'Hello from the main thread.' )};

    return win;
}

electronApp.on('ready', () => {
    win = createWindow();
});

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

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

// Listen for message from (any) render thread.
electronIpcMain.on('message:fromRender', (event, message) => {
    console.log(message);
})
Run Code Online (Sandbox Code Playgroud)

您会注意到我添加了 2 个新的代码部分。一种用于向渲染线程发送消息,另一种用于从渲染线程接收特定消息。


最后,让我们向基本index.html文件添加功能。

index.html(渲染线程)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    
    <body>
        <label for ="button">Send message to main thread: </label>
        <input type="button" id="button" value="Send">        
    </body>
    
    <script>
        // Listen for message from the main thread
        window.ipcRender.receive('message:toRender', (message) => {
            console.log(message);
        });
        
        document.getElementById('button').addEventListener('click', () => {
            // Send a message to the main thread
            window.ipcRender.send('message:fromRender', 'Hello from the render thread.');
        });
    </script>
</html>
Run Code Online (Sandbox Code Playgroud)

启动应用程序后,渲染线程控制台应显示Hello from the main thread

单击该Send按钮后,主线程应显示Hello from the render thread

如果您需要任何澄清或进一步解释,请告诉我。