IPC: от главного процесса к странице
Иногда событие происходит в главном процессе, а реагировать на него должна страница: выбран пункт меню, окно потеряло фокус, файл изменился. Тогда главный процесс отправляет сообщение конкретному окну через webContents.send, а страница заранее подписывается на канал. Ответа такое сообщение не ждёт.
Отправка из главного процесса
webContents — объект окна, который управляет его страницей. Добавьте в createWindow в main.js:
// main.js
function createWindow() {
const win = new BrowserWindow({
width: 900,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
win.loadFile('index.html');
win.on('focus', () => win.webContents.send('window:focus', true));
win.on('blur', () => win.webContents.send('window:focus', false));
}Когда окно получает или теряет фокус, странице уходит сообщение по каналу window:focus со значением true или false.
Подписка в preload
Страница не видит ipcRenderer, поэтому preload даёт ей функцию подписки:
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('notes', {
load: () => ipcRenderer.invoke('notes:load'),
onFocusChange: (callback) => {
ipcRenderer.on('window:focus', (event, focused) => callback(focused));
},
});ipcRenderer.on вызывает обработчик на каждое сообщение. В callback передаётся только значение, без объекта event: в нём есть ссылки на внутренности IPC, и отдавать их странице не нужно.
Реакция страницы
// renderer.js
window.notes.onFocusChange((focused) => {
document.body.style.opacity = focused ? '1' : '0.6';
});Переключитесь на другую программу — окно «Заметок» станет бледнее. Вернитесь — снова станет ярким.
Отписка
Если подписка нужна не всё время, preload может вернуть функцию отписки:
// preload.js
onFocusChange: (callback) => {
const listener = (event, focused) => callback(focused);
ipcRenderer.on('window:focus', listener);
return () => ipcRenderer.removeListener('window:focus', listener);
},Страница сохраняет результат вызова onFocusChange и вызывает его, когда сообщения больше не нужны. В компонентах React так отписываются при удалении компонента.
Два направления
| Направление | Главный процесс | Preload |
|---|---|---|
| Страница → главный, с ответом | ipcMain.handle | ipcRenderer.invoke |
| Страница → главный, без ответа | ipcMain.on | ipcRenderer.send |
| Главный → страница | win.webContents.send | ipcRenderer.on |
Частая ошибка
Сообщение, отправленное сразу после loadFile, теряется: страница ещё не загрузилась и не подписалась на канал. Если данные нужны при запуске, либо пусть страница сама запросит их через invoke, либо отправляйте сообщение после события загрузки: win.webContents.on('did-finish-load', () => ...).