Electron 使用方法,从入门到精通

官方文档:https://www.electronjs.org/zh/docs

进程通信

在 Electron 中,主进程和渲染进程之间可以通过 IPC(Inter-Process Communication,进程间通信) 来传递数据。Electron 提供了 ipcMain 和 ipcRenderer 模块来实现这种通信。

1.主进程到渲染进程的通信

主进程通过 webContents.send 方法向渲染进程发送消息:

const { app, BrowserWindow } = require('electron');

let mainWindow = null;

app.whenReady().then(() => {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');

  // 主进程向渲染进程发送数据
  mainWindow.webContents.send('main-to-renderer', { message: 'Hello from Main Process!' });
});

渲染进程通过 ipcRenderer.on 或 ipcRenderer.once 方法监听主进程发送的消息:

const { ipcRenderer } = require('electron');

// 监听主进程发送的消息
ipcRenderer.on('main-to-renderer', (event, data) => {
  console.log('Received data from Main Process:', data);
});

2.渲染进程到主进程的通信

渲染进程可以通过 ipcRenderer.send 方法向主进程发送消息:

const { ipcRenderer } = require('electron');

// 向主进程发送数据
ipcRenderer.send('renderer-to-main', { message: 'Hello from Renderer Process!' });

主进程通过 ipcMain.on 或 ipcMain.once 方法监听渲染进程发送的消息:

const { app, BrowserWindow, ipcMain } = require('electron');

let mainWindow = null;

app.whenReady().then(() => {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');

  // 监听渲染进程发送的消息
  ipcMain.on('renderer-to-main', (event, data) => {
    console.log('Received data from Renderer Process:', data);
  });
});

3.同步通信(请求-响应模式)

主进程通过 ipcMain.handle 方法处理渲染进程的请求:

const { app, BrowserWindow, ipcMain } = require('electron');

let mainWindow = null;

app.whenReady().then(() => {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
      contextIsolation: false
    }
  });

  mainWindow.loadFile('index.html');

  // 处理渲染进程的请求
  ipcMain.handle('get-data', async (event, data) => {
    console.log('Received request from Renderer Process:', data);
    return { message: 'Response from Main Process' };
  });
});

渲染进程通过 ipcRenderer.invoke 方法发送请求并等待响应:

const { ipcRenderer } = require('electron');

// 发送请求并等待响应
ipcRenderer.invoke('get-data', { message: 'Request from Renderer Process' })
  .then((response) => {
    console.log('Received response from Main Process:', response);
  });

4.preload.js

从 Electron 5 开始,contextIsolation 默认为 true,这意味着渲染进程无法直接访问 Node.js 模块。为了在安全的环境下传递数据,可以使用 preload.js:

const { app, BrowserWindow } = require('electron');

let mainWindow = null;

app.whenReady().then(() => {
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'), // 指定 preload.js 文件
      contextIsolation: true
    }
  });

  mainWindow.loadFile('index.html');
});

preload.js 是一个特殊的脚本,运行在渲染进程中,但可以访问主进程的 API:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  sendMessage: (message) => ipcRenderer.send('renderer-to-main', message),
  receiveMessage: (callback) => ipcRenderer.on('main-to-renderer', callback),
  invoke: (channel, data) => ipcRenderer.invoke(channel, data)
});

渲染进程通过 preload.js 暴露的 API 访问主进程 :

// 使用 preload.js 暴露的 API
window.electronAPI.sendMessage({ message: 'Hello from Renderer Process!' });

window.electronAPI.receiveMessage((event, data) => {
  console.log('Received data from Main Process:', data);
});

window.electronAPI.invoke('get-data', { message: 'Request from Renderer Process' })
  .then((response) => {
    console.log('Received response from Main Process:', response);
  });