首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从Main发送消息到Renderer

从Main发送消息到Renderer
EN

Stack Overflow用户
提问于 2022-03-21 18:56:01
回答 2查看 652关注 0票数 2

有人能帮我一下吗。我完全搞不懂怎么解决这个问题。我现在花了大约一周的时间试图找到解决这个问题的方法,但结果却很短,而且网上似乎缺乏一个可靠的解决方案。我制作了一个github存储库,试图演示这个问题。

简而言之,我在我的应用程序中实现了一个状态栏,我想用各种字符串消息填充它。这些消息将从导入电子的js文件中包含的函数发送,这意味着它没有直接访问Renderer的权限。那么我将如何将这些消息发送给渲染者。我假设这需要使用ContextBridge来完成,但是我不知道如何成功地做到这一点,所以如果您的响应只是将我链接到上下文桥文档,那么就不用麻烦了,lol --我已经疲惫不堪了。我正在考虑的另一种选择是使用自定义事件,但我也不确定这是否能解决问题。

下面是我试图在github上与回购一起做的一个例子。如果你做了一个拉-请求修复回购,我很高兴地合并和保持回购的公众,让其他人受益并与社区分享。https://github.com/JokerMartini/statusbar

作为一个小问题,我不知道为什么我不能再从没有加载到呈现线程的js文件中从'app‘调用getPath。

我从Renderer触发一个方法

index.vue

代码语言:javascript
复制
const doWork = () => {
    window.messenger.doWork();
}

electron-preload.js

代码语言:javascript
复制
import { contextBridge } from "electron";

const messenger = require("../src/helpers/messenger");
contextBridge.exposeInMainWorld("messenger", messenger);

messenger.js

代码语言:javascript
复制
const { app } = require("electron");
const path = require("path");

// using electron module to demonstrate this file can't be imported into renderer
export function showMessage(msg) {
  const dir = path.join(app.getPath("documents"), "presets");
  console.log(dir);
  // TODO: send message to renderer...
}

export function doWork() {
  console.log("Doing working...");

  // step 1: long process
  showMessage("Processing step 1...");

  // step 2: long process
  showMessage("Processing step 2...");

  // step 3: long process
  showMessage("Processing step 3...");
}

中的状态栏中显示从主到呈现程序发送的消息。

main.vue

代码语言:javascript
复制
<q-footer>
     <q-bar>
        <span class="text-caption">Show message here...</span>
    </q-bar>
</q-footer>

**更新01 **

由于某种原因,我的消息没有在渲染器中接收到。下面是我的代码更改

electron-preload.js

代码语言:javascript
复制
import { contextBridge, ipcRenderer } from "electron";

contextBridge.exposeInMainWorld("electronAPI", {
  setStatus: (callback, func) =>
    ipcRenderer.on("set-status", (event, ...args) => func(...args)),
});

index.vue

代码语言:javascript
复制
<template>
  <q-page class="flex flex-center">
    <q-btn label="Show Message" @click="doWork" />
  </q-page>
</template>

<script>
import { defineComponent } from "vue";

export default defineComponent({

  setup() {
    // send message for testing...
    const doWork = () => {
      window.electronAPI.setStatus("sfsfsdfsd");
    };

    // recieve status messages...
    window.electronAPI.setStatus("set-status", (data) => {
      console.log("STATUS:", data);
      // TODO $store.dispatch("....");
    });

    return {
      doWork,
    };
  },
});
</script>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-03-22 13:01:38

一种对我有用的技术是不使用preload.js脚本来定义具体的实现。相反,我使用preload.js脚本只定义我可以在主线程和呈现线程之间进行通信的通道(名称)。分开你的顾虑。在主线程脚本和呈现线程脚本中实现具体的功能。

preload.js

代码语言:javascript
复制
// 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': [],
        // From main to render.
        'receive': [
            'message:update' // Here is your channel name
        ],
        // 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);
            }
        }
    }
);

注意:虽然我不使用Vue.js,但是您应该获得以下两个文件的要点。

main.js (主线程)

代码语言:javascript
复制
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;

const nodePath = require("path");

let window;

function createWindow() {
    const 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;
}

electronApp.on('ready', () => {
    window = createWindow();
    
    // Send a message to the window.
    window.webContents.send('message:update', 'Doing work...');
});

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

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

index.html (渲染线程)

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    
    <body>
        <span id="text-caption">Show message here...</span>
    </body>
    
    <script>      
        // Listen for message updates from the main thread.
        window.ipcRender.receive('message:update', (message) => {
            document.getElementById('text-caption').innerText = message;
        });
    </script>
</html>
票数 3
EN

Stack Overflow用户

发布于 2022-03-22 07:29:20

您希望使用ipcMain (在主进程中)和ipcRenderer (在呈现程序过程中)。如果您将您的脚本与https://www.electronjs.org/docs/latest/tutorial/ipc中的示例进行比较,这就是所缺少的。

(有一个一节,专门介绍如何对呈现器进行处理。。)

这曾经更清晰、更简单,但更有可能被滥用。所以最好忽略任何超过一年左右的在线教程。(虽然contextBridge是很新的,所以如果他们提到它,那么它们应该是最近的。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71562748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档