electron vue 管理系统(Electron结合Vue3开发桌面应用程序-菜单篇)
electron vue 管理系统(Electron结合Vue3开发桌面应用程序-菜单篇)先看下不同类型的效果:{ label: '菜单通用角色' submenu: [ { label: '撤销' role: 'undo' } { label: '关于' role: 'about' } { label: '重做' role: 'redo' } { label: '剪切' role: 'cut'

在上讲主要介绍了基础环境搭建,下面再给大家系统介绍下Electron菜单功能,菜单主要分为菜单栏 原生菜单 和 上下文菜单(特定区域右键菜单、托盘图标菜单)。
先看下效果图:

主进程(background.js主入口文件)
1.通过模板方式创建
    // 第一种方式:通过模板创建菜单
    const isMac = process.platform === 'darwin' // 是否mac平台变量
    const menuTemp = [
        // 下面用到 扩展运算符三个点... 来转换用逗号分隔的参数序列
        ...(isMac ? [{
            label: '苹果一级菜单' 
            submenu: []
        }] : [
            {
                label: '一级菜单' 
                submenu: [
                    {
                        type: 'submenu' 
                        label: '二级菜单' 
                        submenu: [{
                            label: '三级菜单'
                        }]
                    } 
                    {type: 'checkbox'  label: '复选菜单项'  checked: true} 
                    {type: 'radio'  label: '单选1'  checked: true} 
                    {type: 'radio'  label: '单选2'} 
                    {type: 'separator'} 
                    {label: '标签'  sublabel: '附标签'} 
                    {
                        label: '有图标菜单项' 
                        icon: nativeImage.createFromPath(path.join(__static  'favicon.ico')).resize({
                            width: 16 
                            height: 16
                        })
                    } 
                    {label: '有唯一ID的标签项'  id: 'bianchengre'} 
                    {label: '不可点击选项'  enabled: false} 
                    {
                        label: '有自定义点击事件'  click: (menuItem  browserwindow  event) => {
                            console.log(menuItem.label)
                            console.log(browserWindow.title)
                            console.log(event)
                        }
                    } 
                    {label: '不显示菜单项,可以通过事件动态变化'  visible: false} 
                    {role: 'quit'  accelerator: 'CommandOrControl W'} 
                ]
            } 
            {
                label: '关于' 
                role: 'about'
            } 
        ]) 
    ]
    const menu = Menu.buildFromTemplate(menuTemp)
    Menu.setApplicationMenu(menu)
    
2.通过MenuItem实例动态创建。
    // 第二种方式:动态创建菜单
    const menu = new Menu()
    const itemAbout = new MenuItem({label: '关于' role: 'about'})
    menu.append(itemAbout)
    Menu.setApplicationMenu(menu)菜单的角色
    
electron 内置封装一些预置角色,大家可以根据情况,是否使用预置角色,还是自定义菜单点击事件。
效果如下:

{
    label: '菜单通用角色' 
    submenu: [
        {
            label: '撤销' 
            role: 'undo' 
        } 
        {
            label: '关于' 
            role: 'about' 
        } 
        {
            label: '重做' 
            role: 'redo' 
        } 
        {
            label: '剪切' 
            role: 'cut' 
        } 
        {
            label: '复制' 
            role: 'copy' 
        } 
        {
            label: '粘贴' 
            role: 'paste' 
        } 
        {
            label: '粘贴并匹配样式' 
            role: 'pasteAndMatchStyle' 
        } 
        {
            label: '全选' 
            role: 'selectAll' 
        } 
        {
            label: '删除' 
            role: 'delete' 
        } 
        {
            label: '最小化' 
            role: 'minimize' 
        } 
        {
            label: '关闭窗口' 
            role: 'close' 
        } 
        {
            label: '退出程序' 
            role: 'quit' 
        } 
        {
            label: '重载' 
            role: 'reload' 
        } 
        {
            label: '强制撤销' 
            role: 'forceReload' 
        } 
        {
            label: '开发者工具' 
            role: 'toggleDevTools' 
        } 
        {
            label: '切换全屏' 
            role: 'togglefullscreen' 
        } 
        {
            label: '重置缩放' 
            role: 'resetZoom' 
        } 
        {
            label: '放大10%' 
            role: 'zoomIn' 
        } 
        {
            label: '缩小10%' 
            role: 'zoomOut' 
        } 
        {
            label: '切换拼写检查器' 
            role: 'toggleSpellChecker' 
        } 
        {
            label: '文件菜单' 
            role: 'fileMenu' 
        } 
        {
            label: '编辑菜单' 
            role: 'editMenu' 
        } 
        {
            label: '查看菜单' 
            role: 'viewMenu' 
        } 
        {
            label: '窗口菜单' 
            role: 'windowMenu' 
        } 
    ]
} 
    
以上我只列举了通用的角色,还有windows 和 macos独有的角色,大家根据跨平台需要,自定通过process.platform 判断平台对应显示的功能菜单即可。
菜单的类型先看下不同类型的效果:

菜单类型主要有:
- normal 默认类型,不加type 默认normal类型
 - separator 分隔符,通常常用的几个功能一起添加分隔符
 - submenu 子菜单,可以嵌套成为多级菜单
 - checkbox 复选类型,可以勾选、取消当前菜单选择
 - radio 单选类型,多个菜单项之间只能选择一个
 
关键技术:使用Electron nativeImage实现创建图片并调整合适大小
{
    label: '有图标菜单项' 
    icon: nativeImage.createFromPath(path.join(__static  'favicon.ico')).resize({
        width: 16 
        height: 16
    })
} 右键上下文菜单案例:
    
一般特定区域 上下文菜单项是不同的,由渲染进程来通知主进程根据需要展示内容,先看下效果:

具体实现代码:
1.background.js主进程
// main
ipcMain.on('show-context-menu'  (event) => {
    const template = [
        {
            label: 'Electron   vue3' 
            icon: nativeImage.createFromPath(path.join(__static  'favicon.ico')).resize({
                width: 16 
                height: 16
            }) 
        } 
        {
            label: '自定义菜单' 
            click: () => { event.sender.send('context-menu-command'  'menu-item-1') }
        } 
        { type: 'separator' } 
        { label: '刷新'  role: 'reload' }
    ]
    const menu = Menu.buildFromTemplate(template)
    menu.popup(BrowserWindow.fromWebContents(event.sender))
})
    
2.渲染进程 preload.js预加载脚本中
const {contextBridge  ipcRenderer} = require('electron');
contextBridge.exposeInMainWorld(
    'electron' 
    {
        contextMenu: () => {
            ipcRenderer.send('show-context-menu')
        } 
    }
)
ipcRenderer.on('context-menu-command'  (e  command) => {
    console.log(e)
    console.log(command)
})
    
3.前端页面Home.vue
<template>
    <div class="home">
        <div
                id="contextArea"
                style="width: 400px; height: 300px;line-height: 300px; background: lightblue; margin: 0 auto;"
                @contextmenu="testContextMenu($event)"
        >
            此区域 右键 可以弹出 特定 上下文菜单
        </div>
    </div>
</template>
<script>
    export default {
        name: 'Home' 
        methods: {
          testContextMenu(e){
            e.preventDefault()
            window.electron.contextMenu()
          }
        } 
    }
</script>
托盘图标上下文案例:
    
一般关闭 任务栏到托盘的时候,点击托盘图标右键等操作的时候 会弹出 上下文菜单,先看下效果:


实现代码:
backgroud.js 关键代码
app.whenReady().then(() => {
    const icon = nativeImage.createFromPath(path.join(__static  'bianchengre.png')).resize({
        width: 16 
        height: 16
    })
    tray = new Tray(icon)
    const contextMenu = Menu.buildFromTemplate([
        {
            label: 'Electron   vue3' 
            icon: nativeImage.createFromPath(path.join(__static  'favicon.ico')).resize({
                width: 16 
                height: 16
            }) 
        } 
        { type: 'separator' } 
        { label: '退出'  role: 'quit' }
    ])
    tray.setToolTip('编程热:编程源于热爱')
    tray.setContextMenu(contextMenu)
    tray.on('click' ()=>{
        // 单击图标显示主窗口
        win.show()
    })
    tray.on('double-click' ()=>{
        // 双击图标显示主窗口
        win.show()
    })
})
    
监听窗口关闭事件,实现关闭的时候 提示对话框,选择直接退出 还是 隐藏到托盘
    win.on('close' (event)=>{
        event.preventDefault()
        dialog.showMessageBox({
            title: '确定关闭吗' 
            buttons: ['直接关闭' '最小化托盘' '取消']
        }).then((data)=>{
            if(data.response === 0){
                // 直接退出
                app.exit()
            } else if(data.response === 1) {
                // 最小化托盘
                win.hide()
            } else {
                // pass
            }
        })
    })
    
菜单相关的知识点就先讲到这里,大家过程中有问题可以随时留言发出来探讨~




