通过 Electron IPCmain 通道向 vue 实例发送消息只能以一种方式工作
Sending messages through Electron IPCmain channel to vue instance only works one way
我正在尝试在主电子进程和 vue 实例之间来回发送消息。到目前为止我所拥有的是
Preload.js:
import { contextBridge, ipcRenderer } from 'electron'
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
window.ipcRenderer = require('electron').ipcRenderer;
contextBridge.exposeInMainWorld('ipcRenderer', {
//Render (Vue) to main (Electron)
send: (channel, data) => {
let validChannels = ['clientMessage'] // <-- Array of all ipcRenderer Channels used in the client
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data)
}
},
//Main (Electron) to Render (Vue)
on: (channel, func) => {
let validChannels = ['electronMessage'] // <-- Array of all ipcMain Channels used in the electron
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args))
}
}
})
所以我在 ipcRender 中有 2 个白名单通道,一个叫做 'clientMessage' 从 vue 实例发送消息到电子主进程,另一个是 'electronMessage' 从电子主进程发送消息处理到 vue 实例。
在我的 background.js 中,我有以下内容:
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
ipcMain.on('clientMessage', (event, args) => {
console.log('received a message from vue: '+args)
event.sender.send('message','return Message from electron'+args);
});
在我的 app.Vue 中我有:
mounted () {
window.ipcRenderer.on('electronMessage', (event, data) => {
console.log('message from electron: '+data)
})
},
methods: {
sendMessage(){
window.ipcRenderer.send('clientMessage','testing')
}
}
该应用程序运行良好,当我调用 sendMessage 函数时,我在电子终端上正确地获得了一个控制台日志,提示已收到消息。很明显 vue -> electron messaging 有效,但为什么它不能用于相反的情况?
您的contextBridge.exposeInMainWorld
“键”是ipcRenderer.send
和ipcRenderer.receive
。
您必须使用这些键来访问您定义的 preload.js
IPC 方法。即:send
和 on
.
具体来说,要使用 ipcRender.on(...)
方法,您可以使用 window.ipcRenderer.receive(...)
调用它。
app.Vue
(渲染线程)
// To send a message from render thread to main thread.
window.ipcRenderer.send('clientMessage','testing'); // Working
// To receive a message from main thread to render thread.
window.ipcRenderer.receive('electronMessage', (event, data) => {
console.log('message from electron: ' + data);
});
我知道为什么了,从electron主进程向renderer实例发送消息的方式不一样。由于始终只有一个 electron 主进程 运行,我们可以在 vue 渲染器实例中简单地执行 window.ipcRenderer.send('', 'your message'),但由于可以有多个渲染器实例 运行,主电子进程需要知道将其发送到哪个渲染进程。
所以在你的 main.js/background.js 中不管你是什么 .js 运行 electron 主进程。这样做:
let win;
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: true,
preload: path.join(__dirname, "preload.js")
}
})
.
.
.
然后向渲染实例发送消息:
win.webContents.send('<channelName>','your message')
以这种方式将其发送到正确的渲染进程。所以我的代码最后看起来是这样的:
ipcMain.on('clientMessage', (event, args) => {
console.log('received a message from vue: '+args)
win.webContents.send('electronMessage','Reply from main process: '+args)
});
我正在尝试在主电子进程和 vue 实例之间来回发送消息。到目前为止我所拥有的是
Preload.js:
import { contextBridge, ipcRenderer } from 'electron'
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
window.ipcRenderer = require('electron').ipcRenderer;
contextBridge.exposeInMainWorld('ipcRenderer', {
//Render (Vue) to main (Electron)
send: (channel, data) => {
let validChannels = ['clientMessage'] // <-- Array of all ipcRenderer Channels used in the client
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data)
}
},
//Main (Electron) to Render (Vue)
on: (channel, func) => {
let validChannels = ['electronMessage'] // <-- Array of all ipcMain Channels used in the electron
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args))
}
}
})
所以我在 ipcRender 中有 2 个白名单通道,一个叫做 'clientMessage' 从 vue 实例发送消息到电子主进程,另一个是 'electronMessage' 从电子主进程发送消息处理到 vue 实例。
在我的 background.js 中,我有以下内容:
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
ipcMain.on('clientMessage', (event, args) => {
console.log('received a message from vue: '+args)
event.sender.send('message','return Message from electron'+args);
});
在我的 app.Vue 中我有:
mounted () {
window.ipcRenderer.on('electronMessage', (event, data) => {
console.log('message from electron: '+data)
})
},
methods: {
sendMessage(){
window.ipcRenderer.send('clientMessage','testing')
}
}
该应用程序运行良好,当我调用 sendMessage 函数时,我在电子终端上正确地获得了一个控制台日志,提示已收到消息。很明显 vue -> electron messaging 有效,但为什么它不能用于相反的情况?
您的contextBridge.exposeInMainWorld
“键”是ipcRenderer.send
和ipcRenderer.receive
。
您必须使用这些键来访问您定义的 preload.js
IPC 方法。即:send
和 on
.
具体来说,要使用 ipcRender.on(...)
方法,您可以使用 window.ipcRenderer.receive(...)
调用它。
app.Vue
(渲染线程)
// To send a message from render thread to main thread.
window.ipcRenderer.send('clientMessage','testing'); // Working
// To receive a message from main thread to render thread.
window.ipcRenderer.receive('electronMessage', (event, data) => {
console.log('message from electron: ' + data);
});
我知道为什么了,从electron主进程向renderer实例发送消息的方式不一样。由于始终只有一个 electron 主进程 运行,我们可以在 vue 渲染器实例中简单地执行 window.ipcRenderer.send('', 'your message'),但由于可以有多个渲染器实例 运行,主电子进程需要知道将其发送到哪个渲染进程。
所以在你的 main.js/background.js 中不管你是什么 .js 运行 electron 主进程。这样做:
let win;
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: true,
preload: path.join(__dirname, "preload.js")
}
})
.
.
.
然后向渲染实例发送消息:
win.webContents.send('<channelName>','your message')
以这种方式将其发送到正确的渲染进程。所以我的代码最后看起来是这样的:
ipcMain.on('clientMessage', (event, args) => {
console.log('received a message from vue: '+args)
win.webContents.send('electronMessage','Reply from main process: '+args)
});