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