在使用 electron-vite-vue 开发桌面应用时,我们常常需要打开多个窗口来分离模块、提升用户体验。本篇文章将基于该项目脚手架结构,构建一套完整的多窗口管理系统,包括:
- ✅ 主窗口与子窗口统一管理
- ✅ 渲染进程调用打开窗口
- ✅ 多窗口通信机制
📦 项目结构扩展
electron-vite-vue/
├── electron/
│ ├── main/
│ │ ├── index.ts # 主进程入口
│ │ ├── ipcHandlers.ts # IPC 注册
│ │ └── windows.ts # 窗口创建与管理
│ └── preload/
│ └── index.ts # contextBridge 暴露 API
├── src/
│ ├── App.vue # 调用入口
│ ├── main.ts
│ └── router/index.ts # Vue 路由注册
🛠 主进程窗口管理:windows.ts
// electron/main/windows.ts
import { BrowserWindow } from 'electron'
import path from 'path'
const windows = new Map<string, BrowserWindow>()
export function createMainWindow(): BrowserWindow {
const win = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
}
})
const url = process.env.VITE_DEV_SERVER_URL || ''
win.loadURL(`${url}`)
windows.set('main', win)
return win
}
export function createWindow(name: string, hashRoute: string): BrowserWindow {
if (windows.has(name)) {
windows.get(name)?.focus()
return windows.get(name)!
}
const child = new BrowserWindow({
width: 700,
height: 500,
parent: windows.get('main'),
webPreferences: {
preload: path.join(__dirname, '../preload/index.js'),
}
})
const url = process.env.VITE_DEV_SERVER_URL || ''
child.loadURL(`${url}#${hashRoute}`)
child.on('closed', () => {
windows.delete(name)
})
windows.set(name, child)
return child
}
💬 注册 IPC:ipcHandlers.ts
import { ipcMain } from 'electron'
import { createWindow } from './windows'
export function setupIpcHandlers() {
ipcMain.on('open-window', (_, { name, route }) => {
createWindow(name, route)
})
}
并在 main/index.ts
中引入:
import { setupIpcHandlers } from './ipcHandlers'
setupIpcHandlers()
🛡️ Preload 暴露 API:preload/index.ts
import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('electronAPI', {
openWindow: (name: string, route: string) => {
ipcRenderer.send('open-window', { name, route })
}
})
💻 渲染进程中打开窗口:App.vue
<template>
<button @click="openSettings">打开设置窗口</button>
</template>
<script setup lang="ts">
function openSettings() {
window.electronAPI.openWindow('settings', '/settings')
}
</script>
你需要在 Vue Router 中配置对应页面:
// src/router/index.ts
{
path: '/settings',
component: () => import('@/views/Settings.vue')
}
📡 跨窗口通信(主窗口 → 子窗口)
// 主进程中
childWindow.webContents.send('message', 'hello from main')
// 渲染进程监听
ipcRenderer.on('message', (_, data) => {
console.log('收到:', data)
})
🧠 建议实践
建议 | 描述 |
---|---|
窗口唯一性 | 用 Map 管理窗口,防止重复打开 |
路由注入 | 使用 Hash 模式支持 Vue 内部路由跳转 |
通信隔离 | 使用窗口名标记通信目标 |
生命周期管理 | closed 事件中清理引用 |
✅ 总结
通过对 electron-vite-vue
项目进行多窗口扩展,我们实现了:
- ✅ 多窗口集中管理
- ✅ 渲染进程一键打开子窗口
- ✅ 支持页面级路由跳转与通信
这套结构适用于多页面应用、后台系统、配置面板等场景,为你的桌面应用注入更多灵活性。
👉 延伸阅读: