Electron + Vue3 进程通信全攻略——主进程与渲染进程的那点事。
本文对比了Electron中主进程与渲染进程通信的两种方式。传统send+on模式适合单向通知,需手动管理回复逻辑;现代invoke+handle模式基于Promise,简化了双向通信和错误处理。对于主进程主动推送数据,推荐使用webContents.send实现实时通信。文中提供了Vue3项目中的完整代码示例,建议根据场景需求选择通信方式:无返回值用send,需要返回数据用invoke,实时推送
·
文章目录
前言
在 Electron 开发中,主进程与渲染进程的通信是构建桌面应用的核心能力。随着 Electron 版本的迭代,通信方式也在不断优化。本文将以 Vue3 项目为例,对比传统 send 模式与现代 invoke 模式,并给出最佳实践方案。
一、渲染进程到主进程的通信的两种模式
传统模式:ipcRenderer.send+ ipcMain.on
适用场景:简单的单向通信(如渲染进程通知主进程执行操作,不关心结果)。
实现步骤
主进程(main.js) :
const { ipcMain } = require('electron');
ipcMain.on('log-message', (event, message) => {
console.log('收到渲染进程消息:', message);
// 回复消息(可选)
event.reply('log-reply', '消息已接收');
});
预加载脚本(preload.js) :
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
sendLogMessage: (message) => ipcRenderer.send('log-message', message),
onLogReply: (callback) => ipcRenderer.on('log-reply', (_, reply) => callback(reply)),
});
渲染进程(Vue3 组件) :
<template>
<div>
<button @click="sendMessage">发送消息</button>
<div v-if="reply">主进程回复:{{ reply }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const reply = ref('');
const sendMessage = () => {
window.electronAPI.sendLogMessage('Hello from Renderer!');
};
// 监听主进程回复
window.electronAPI.onLogReply((res) => {
reply.value = res;
});
</script>
特点:
- 代码复杂:需要手动管理消息通道和回复逻辑。
- 无返回值:
send本身不返回 Promise,需通过event.reply或send的另一个实例实现双向通信。 - 适合场景:简单的通知或不需要返回值的操作。
现代模式:ipcRenderer.invoke + ipcMain.handle
适用场景:需要返回结果的双向通信(如文件操作、系统信息查询)。
实现步骤
主进程(main.js) :
const { ipcMain } = require('electron');
ipcMain.handle('get-system-info', async () => {
return {
platform: process.platform,
arch: process.arch,
version: process.versions.electron,
};
});
预加载脚本(preload.js) :
contextBridge.exposeInMainWorld('electronAPI', {
getSystemInfo: () => ipcRenderer.invoke('get-system-info'),
});
渲染进程(Vue3 组件) :
<template>
<div>
<button @click="fetchSystemInfo">获取系统信息</button>
<div v-if="info">系统信息:{{ info }}</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const info = ref(null);
const fetchSystemInfo = async () => {
try {
info.value = await window.electronAPI.getSystemInfo();
} catch (error) {
console.error('获取系统信息失败:', error);
}
};
</script>
特点:
- 代码简洁:基于 Promise,逻辑更清晰。
- 直接返回值:
invoke返回 Promise,适合需要返回结果的场景。 - 错误处理方便:可直接用
try/catch捕获错误。 - 推荐场景:文件操作、系统信息查询、数据库查询等。
如何选择通信模式?
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 渲染进程通知主进程(无返回值) | send + on |
简单直接,无需返回值 |
| 渲染进程请求主进程返回数据 | invoke + handle |
代码简洁,支持 Promise 和错误处理 |
二、主进程向渲染进程通信的方式
webContents.send(推荐方式)
适用场景:主进程主动推送数据到渲染进程(如状态更新、实时通知)。
实现步骤
主进程(main.js) :
const { BrowserWindow, app } = require('electron');
let mainWindow;
app.whenReady().then(() => {
mainWindow = new BrowserWindow({ /* 窗口配置 */ });
// 模拟主进程主动推送数据
setInterval(() => {
// 发送消息到渲染进程
mainWindow.webContents.send('progress-update', {
percent: Math.floor(Math.random() * 100), // 随机进度
status: '处理中...',
});
}, 1000);
});
预加载脚本(preload.js) :
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
onProgressUpdate: (callback) => {
// 暴露监听器给渲染进程
return ipcRenderer.on('progress-update', (_, data) => callback(data));
},
});
渲染进程(Vue3 组件) :
<template>
<div>
<h2>任务进度</h2>
<progress :value="progress.percent" max="100"></progress>
<p>{{ progress.status }}</p>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';
const progress = ref({ percent: 0, status: '等待中...' });
let cleanup = null;
onMounted(() => {
// 监听主进程推送的数据
cleanup = window.electronAPI.onProgressUpdate((data) => {
progress.value = data;
});
});
onBeforeUnmount(() => {
if (cleanup) cleanup(); // 清理监听器,避免内存泄漏
});
</script>
特点:
- 主动推送:主进程无需等待渲染进程请求,直接发送数据。
- 实时性强:适合进度条、状态更新等实时场景。
- 需清理监听器:在渲染进程中,组件卸载时需清理监听器。
总结
通过本文的对比和示例,你可以根据具体场景选择最适合的双向通信方式,为 Vue3 + Electron 开发提供高效、安全的通信方案!
更多推荐

所有评论(0)