Electron + Vite + Vue 多窗口管理实战指南

在使用 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 项目进行多窗口扩展,我们实现了:

  • ✅ 多窗口集中管理
  • ✅ 渲染进程一键打开子窗口
  • ✅ 支持页面级路由跳转与通信

这套结构适用于多页面应用、后台系统、配置面板等场景,为你的桌面应用注入更多灵活性。


👉 延伸阅读:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值