Контекстное меню
Контекстное меню — меню, которое появляется по правому щелчку мыши. В Electron его по умолчанию нет вообще: правый щелчок по полю ввода ничего не показывает. Меню создаётся тем же Menu.buildFromTemplate, что и меню приложения, но показывается методом popup в нужном месте.
Меню для полей ввода
Главный процесс узнаёт о правом щелчке по событию context-menu у webContents окна. Добавьте в createWindow в main.js:
// main.js
win.webContents.on('context-menu', (event, params) => {
if (!params.isEditable) {
return;
}
const menu = Menu.buildFromTemplate([
{ role: 'cut', label: 'Вырезать' },
{ role: 'copy', label: 'Копировать' },
{ role: 'paste', label: 'Вставить' },
{ type: 'separator' },
{ role: 'selectAll', label: 'Выделить всё' },
]);
menu.popup({ window: win });
});params.isEditable равен true, если щелчок пришёлся на поле ввода. Щёлкните правой кнопкой по полю заметки — появится меню с привычными командами. Роли выполняют действия сами, click писать не нужно.
Что есть в params
| Поле | Значение |
|---|---|
isEditable | Щелчок по полю ввода |
selectionText | Выделенный текст |
linkURL | Адрес ссылки под курсором |
x, y | Координаты щелчка |
Меню для заметки
Чтобы удалить конкретную заметку, главному процессу нужно знать, по какой из них щёлкнули. Это знает только страница, поэтому она сама просит показать меню:
// renderer.js
list.addEventListener('contextmenu', (event) => {
const li = event.target.closest('li');
if (!li) {
return;
}
event.preventDefault();
window.notes.showNoteMenu(Number(li.dataset.index));
});При выводе списка каждому li записывается li.dataset.index = i. Вызов preventDefault отменяет стандартную обработку правого щелчка.
// preload.js
showNoteMenu: (index) => ipcRenderer.send('notes:menu', index),
onDeleteNote: (callback) => ipcRenderer.on('notes:delete', (event, index) => callback(index)),Показ меню в главном процессе
// main.js
ipcMain.on('notes:menu', (event, index) => {
const menu = Menu.buildFromTemplate([
{ label: 'Удалить заметку', click: () => event.sender.send('notes:delete', index) },
]);
menu.popup({ window: BrowserWindow.fromWebContents(event.sender) });
});Ответ не нужен, поэтому используется пара send и ipcMain.on. Выбранный пункт отправляет странице номер заметки по каналу notes:delete.
// renderer.js
window.notes.onDeleteNote(async (index) => {
notes.splice(index, 1);
await window.notes.save(notes);
render();
});Правый щелчок по заметке и пункт «Удалить заметку» убирают её из списка и из файла.
Частая ошибка
Без параметра window метод popup откроет меню у текущего активного окна, и при нескольких окнах оно может появиться не там. Всегда передавайте окно, из которого пришёл щелчок: menu.popup({ window: win }).