Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

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.handleipcRenderer.invoke
Страница → главный, без ответаipcMain.onipcRenderer.send
Главный → страницаwin.webContents.sendipcRenderer.on

Частая ошибка

Сообщение, отправленное сразу после loadFile, теряется: страница ещё не загрузилась и не подписалась на канал. Если данные нужны при запуске, либо пусть страница сама запросит их через invoke, либо отправляйте сообщение после события загрузки: win.webContents.on('did-finish-load', () => ...).

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.