electron实现动态菜单

electron实现动态菜单

前言

编写桌面应用时,时常遇到需要动态菜单的情况,尤其是在使用应用的桌面托盘菜单时。经常需要根据前一次的操作来动态生成菜单。例如,一个应用有两种模式,专业模式和简单模式,专业模式拥有比普通模式细粒度的控制效果,相应的拥有更多的菜单项。而简单模式,一键操作菜单项较少。那么怎样通过菜单选择一个模式,然后动态的生成对应模式的菜单呢?

思路

在electron中并没有给出动态生成菜单的API,我们不能通过简单的传入一个相应的列表来生成菜单。一般来说我们electron在启动时为应用创建一个菜单,这个菜单一旦生成是不可以动态改变,这就意味着我们可以动态删除菜单项。但是菜单对象的属性我们是可以更改的。
在这里插入图片描述

这样我们就有了解决的思路,我们可以通过控制菜单项的visible属性来控制菜单的显示和隐藏。现在我们要做就是拿到菜单项然后修改菜单项的相应属性就可以实现动态的生成菜单了。那么怎样拿到菜单项呢,electron提供了一种方式通过id来拿到某个菜单项getMenuItemById)。使用这种方式生成动态菜单需要注意的是:在菜单的第一次生成时应该将你可能用到的所用菜单都放入到菜单列表中,然后通过控制属性来隐藏或显示。虽然electron也提供了菜单项的插入和追加的方法但是没有提供菜单项的删除方法,因此最好在开始时一次性将所有可能的菜单项都生成,而不是后续的插入或追加。不然容易搞乱思路。

具体实现

const { app, BrowserWindow, Menu } = require("electron");
const EventEmitter = require("events");

const event = new EventEmitter();

function createWindow() {
	const mainWindow = new BrowserWindow({
		width: 800,
		height: 600
	});
	return mainWindow;
}


const menuTemplate = [
	{
		label: "菜单1",
		submenu: [
			{
				label: "菜单1.1",
				type: "radio",
				click: () => {
					event.emit("change-menu", 0);
				}
			},
			{
				type: "radio",
				label: "菜单1.2",
				click: () => {
					event.emit("change-menu", 1);
				}
			},
			{
				type: "radio",
				label: "菜单1.3",
				click: () => {
					event.emit("change-menu", 2);
				}
			}
		]
	},
	{
		label: "菜单2",
		submenu: [
			{
				id: "2.1",
				label: "菜单2.1",
				click: () => {

				}
			},
			{
				id: "2.2",
				label: "菜单2.2",
				click: () => {

				}
			},
			{
				id: "2.3",
				label: "菜单2.3",
				click: () => {

				}
			}
		]
	}
];

function changeMenu2(menu){
	const menu2ID = ["2.1", "2.2", "2.3"];
	const menu2Item = [];
	menu2ID.forEach((item, index) => {
		const menuItem = menu.getMenuItemById(item);
		menuItem.visible = !index;
		menu2Item.push(menuItem);
	});
	event.on("change-menu", (arg)=>{
		menu2Item.forEach((item)=>{
			item.visible = false;
		});
		switch(arg){
			case 0:
				menu2Item[0].visible = true;
				break;
			case 1:
				menu2Item[1].visible = true;
				break;
			default:
				menu2Item[2].visible = true;
				break;
		}
	});
}

app.whenReady().then(() => {
	const menu = Menu.buildFromTemplate(menuTemplate);
	changeMenu2(menu);
	Menu.setApplicationMenu(menu);
	createWindow();
})

代码中使用了node的事件对象来进行所有菜单项的统一管理,每次点击菜单发射一个事件,然后在事件监听中重新生成菜单的显隐。

github示例地址:https://github.com/li725-ll/electron-dynamical-menu.git

实现自定义菜单栏,可以使用 Electron 提供的 Menu 模块。以下是一个使用 Electron Vite Vue 实现自定义菜单栏的步骤: 1. 在 Vue 组件中引入 Electron 的 remote 模块,用于获取主进程的 Menu 对象。 ```javascript import { remote } from 'electron' const Menu = remote.Menu ``` 2. 在 Vue 组件的生命周期钩子函数中创建菜单项,可以使用 Menu.buildFromTemplate 方法创建菜单项的数组。 ```javascript created() { const template = [ { label: '文件', submenu: [ { label: '新建', accelerator: 'CmdOrCtrl+N', click: this.handleNew }, { label: '打开', accelerator: 'CmdOrCtrl+O', click: this.handleOpen }, { type: 'separator' }, { label: '保存', accelerator: 'CmdOrCtrl+S', click: this.handleSave }, { label: '另存为', accelerator: 'Shift+CmdOrCtrl+S', click: this.handleSaveAs }, { type: 'separator' }, { label: '退出', accelerator: 'CmdOrCtrl+Q', click: this.handleQuit } ] }, { label: '编辑', submenu: [ { label: '撤销', accelerator: 'CmdOrCtrl+Z', role: 'undo' }, { label: '重做', accelerator: 'Shift+CmdOrCtrl+Z', role: 'redo' }, { type: 'separator' }, { label: '剪切', accelerator: 'CmdOrCtrl+X', role: 'cut' }, { label: '复制', accelerator: 'CmdOrCtrl+C', role: 'copy' }, { label: '粘贴', accelerator: 'CmdOrCtrl+V', role: 'paste' }, { label: '全选', accelerator: 'CmdOrCtrl+A', role: 'selectAll' } ] } ] const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu) } ``` 3. 在 Vue 组件中实现菜单项的点击事件。 ```javascript methods: { handleNew() { // 新建文件 }, handleOpen() { // 打开文件 }, handleSave() { // 保存文件 }, handleSaveAs() { // 另存为文件 }, handleQuit() { // 退出应用程序 } } ``` 这样就可以在 Electron Vite Vue 应用程序中实现自定义菜单栏了。需要注意的是,菜单项的点击事件可以调用主进程中的方法,例如使用 ipcRenderer 发送消息给主进程,让主进程执行相应的操作。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值