Vue-Electron如何自定义顶部菜单栏?将菜单元素移至标题栏
Electron + Vue 自定义标题栏实现方案
要把系统菜单栏迁移到自定义标题栏,分以下几个核心步骤实现:
1. 主进程配置:隐藏默认菜单栏与系统标题栏
在Electron主进程文件(通常是main.js)中,做以下配置:
- 隐藏系统默认应用菜单栏
- 创建无边框窗口,同时保留窗口的拖动、缩放能力
const { app, BrowserWindow, Menu } = require('electron') function createWindow() { // 隐藏默认应用菜单栏 Menu.setApplicationMenu(null) const mainWindow = new BrowserWindow({ width: 800, height: 600, frame: false, // 去掉系统默认边框和标题栏 webPreferences: { nodeIntegration: true, contextIsolation: false, enableRemoteModule: true } }) mainWindow.loadURL('http://localhost:8080') // Vue开发环境地址,打包后替换为loadFile路径 } app.whenReady().then(createWindow)
2. Vue渲染进程:自定义标题栏组件
在Vue项目中创建自定义标题栏组件(比如components/TitleBar.vue),包含菜单选项和窗口控制按钮,同时通过CSS实现拖动效果:
<template> <div class="title-bar"> <!-- 自定义菜单区域 --> <div class="menu-group"> <button class="menu-item" @click="handleFileMenu">文件</button> <button class="menu-item" @click="handleEditMenu">编辑</button> <button class="menu-item" @click="handleViewMenu">视图</button> </div> <!-- 窗口控制按钮 --> <div class="window-controls"> <button class="control-btn" @click="minimizeWindow">-</button> <button class="control-btn" @click="toggleMaximizeWindow">□</button> <button class="control-btn close-btn" @click="closeWindow">×</button> </div> </div> </template> <script> const { ipcRenderer } = require('electron') export default { methods: { // 菜单逻辑示例:触发主进程对应操作 handleFileMenu() { ipcRenderer.send('trigger-file-menu') }, handleEditMenu() { ipcRenderer.send('trigger-edit-menu') }, handleViewMenu() { ipcRenderer.send('trigger-view-menu') }, // 窗口控制逻辑 minimizeWindow() { ipcRenderer.send('window-minimize') }, toggleMaximizeWindow() { ipcRenderer.send('window-toggle-maximize') }, closeWindow() { ipcRenderer.send('window-close') } } } </script> <style scoped> .title-bar { display: flex; justify-content: space-between; align-items: center; height: 36px; background-color: #2c3e50; color: #fff; padding: 0 12px; -webkit-app-region: drag; /* 允许标题栏拖动窗口 */ } .menu-item, .control-btn { background: transparent; border: none; color: #fff; padding: 8px 12px; cursor: pointer; -webkit-app-region: no-drag; /* 按钮禁止拖动,确保可点击 */ } .menu-item:hover, .control-btn:hover { background-color: #34495e; } .close-btn:hover { background-color: #e74c3c; } .window-controls { display: flex; gap: 4px; } </style>
3. 主进程与渲染进程通信
在主进程中监听渲染进程发送的事件,处理菜单操作和窗口控制:
// 继续在main.js中添加 const { ipcMain, dialog } = require('electron') // 菜单事件处理示例 ipcMain.on('trigger-file-menu', async () => { const result = await dialog.showOpenDialog({ properties: ['openFile'] }) console.log('选中文件:', result.filePaths) // 这里添加业务逻辑 }) // 窗口控制事件监听 ipcMain.on('window-minimize', () => { const window = BrowserWindow.getFocusedWindow() window.minimize() }) ipcMain.on('window-toggle-maximize', () => { const window = BrowserWindow.getFocusedWindow() window.isMaximized() ? window.unmaximize() : window.maximize() }) ipcMain.on('window-close', () => { const window = BrowserWindow.getFocusedWindow() window.close() })
4. 集成自定义标题栏到Vue页面
在Vue主页面(比如App.vue)中引入并使用自定义标题栏:
<template> <div id="app"> <TitleBar /> <!-- 页面核心内容 --> <router-view /> </div> </template> <script> import TitleBar from './components/TitleBar.vue' export default { components: { TitleBar } } </script>
注意事项
- 若使用Electron v12+版本,建议用**预加载脚本(preload.js)**替代直接开启
nodeIntegration,避免安全风险 - 自定义菜单的下拉展开逻辑可通过Vue弹窗组件实现(如Element UI的Dropdown)
- 不同平台(Windows/macOS)的窗口控制按钮样式、位置有差异,可根据平台做适配
内容的提问来源于stack exchange,提问作者Rusty
相关产品推荐
相关产品推荐

