Electron + Vue2 IPC 通讯实例
项目需求, 一直在做 Electron 项目的 IPC 通讯, 顺便写一个 Electron + Vue2 实际混用示例发出来共同学习下,涵盖两种场景:
📌 场景
-
通知类(只告诉主进程做事,不关心返回值) → 用
send/on
。
例子:渲染进程告诉主进程「用户点了检查更新」。 -
请求类(需要结果,像调用 API) → 用
invoke/handle
。
例子:渲染进程请求主进程「获取当前版本号」。
🔹 主进程 (main.js)
import { app, BrowserWindow, ipcMain } from 'electron';let mainWindow;function createWindow() {mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true,contextIsolation: false, // Vue2 项目一般是 false}});mainWindow.loadURL('http://localhost:8080');
}// ------------------ send/on (通知类) ------------------
ipcMain.on('check-for-update', (event) => {console.log('渲染进程通知: 用户点击了检查更新按钮');// 这里可以触发更新逻辑,比如调用 autoUpdater.checkForUpdates()// 可以选择再给渲染进程发消息event.reply('update-status', { status: 'checking' });
});// ------------------ invoke/handle (请求类) ------------------
ipcMain.handle('get-app-version', async () => {console.log('渲染进程请求: 获取版本号');return app.getVersion(); // 直接返回给渲染进程
});app.whenReady().then(createWindow);
🔹 渲染进程 (Vue2 组件示例)
<template><div><button @click="checkUpdate">检查更新</button><button @click="getVersion">获取版本号</button><p>更新状态: {{ updateStatus }}</p><p>当前版本: {{ version }}</p></div>
</template><script>
const { ipcRenderer } = require('electron');export default {data() {return {updateStatus: '',version: ''};},created() {// 监听主进程返回的更新状态ipcRenderer.on('update-status', (event, data) => {this.updateStatus = data.status;});},methods: {// 只通知,不需要返回值checkUpdate() {ipcRenderer.send('check-for-update');},// 请求并等待返回值async getVersion() {this.version = await ipcRenderer.invoke('get-app-version');}}
};
</script>
🔑 运行效果
- 点击「检查更新」 → 主进程日志输出
"用户点击了检查更新按钮"
,并且 UI 里的「更新状态」变成"checking"
。 - 点击「获取版本号」 → 主进程返回 app 版本号,UI 里的「当前版本」直接显示。
✅ 这样你就能在一个项目里同时用 send/on
(事件通知)和 invoke/handle
(请求-响应)。
这里演示了项目中的基本使用, 不过还有个小问题, 可能会重复绑定
。
那接下来我们就更新一步, 把 重复绑定防护写进去(避免 dev 热重载时监听器堆积)?
直接上代码
把 上面的混用示例加上 重复绑定防护,防止开发环境热重载或重复初始化导致 ipcMain.on
堆叠。
🔹 主进程(main.js)示例
import { app, BrowserWindow, ipcMain } from 'electron';let mainWindow;function createWindow() {mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true,contextIsolation: false, // Vue2 项目一般是 false}});mainWindow.loadURL('http://localhost:8080');
}// ------------------ send/on (通知类) ------------------
// 防止重复绑定
if (!ipcMain.listenerCount('check-for-update')) {ipcMain.on('check-for-update', (event) => {console.log('渲染进程通知: 用户点击了检查更新按钮');// 可以发送回渲染进程更新状态event.reply('update-status', { status: 'checking' });});
}// ------------------ invoke/handle (请求类) ------------------
// handle 不会重复堆叠,同一 channel 会覆盖
ipcMain.handle('get-app-version', async () => {console.log('渲染进程请求: 获取版本号');return app.getVersion();
});app.whenReady().then(createWindow);
🔹 渲染进程 (Vue2 组件示例)
<template><div><button @click="checkUpdate">检查更新</button><button @click="getVersion">获取版本号</button><p>更新状态: {{ updateStatus }}</p><p>当前版本: {{ version }}</p></div>
</template><script>
const { ipcRenderer } = require('electron');export default {data() {return {updateStatus: '',version: ''};},created() {// 防止重复绑定ipcRenderer.removeAllListeners('update-status');// 监听主进程返回的更新状态ipcRenderer.on('update-status', (event, data) => {this.updateStatus = data.status;});},methods: {// 只通知,不需要返回值checkUpdate() {ipcRenderer.send('check-for-update');},// 请求并等待返回值async getVersion() {this.version = await ipcRenderer.invoke('get-app-version');}}
};
</script>
🔑 特点
-
send/on + 防重复
- 主进程用
ipcMain.listenerCount('channel')
判断是否已经绑定。 - 渲染进程用
ipcRenderer.removeAllListeners('channel')
先解绑,再绑定。
- 主进程用
-
invoke/handle
- 主进程用
ipcMain.handle
覆盖旧 handler,不会重复。 - 渲染进程用
await ipcRenderer.invoke()
获取返回值。
- 主进程用
-
适合开发环境 HMR
- 不会因为热重载或重新执行模块而导致监听器叠加。
本章完!