electron 主进程与渲染进程通讯

时间:2025-02-07 13:14:02

主进程和渲染器进程

Electron 有两种进程:主进程和渲染进程。

  • 主进程通过创建 BrowserWindow 实例来创建 网页。 每一个 BrowserWindow 实例在其渲染过程中运行网页, 当一个 BrowserWindow 实例被销毁时,对应的渲染过程也会被终止。
  • 主进程 管理 所有网页及其对应的渲染进程。

  • 渲染进程只能管理相应的网页, 一个渲染进程的崩溃不会影响其他渲染进程。
  • 渲染进程通过 IPC 与主进程通信在网在页上执行 GUI 操作。 出于安全和可能的资源泄漏考虑,直接从渲染器进程中调用与本地 GUI 有关的 API 受到限制。

进程之间的通信可以通过 Inter-Process Communication (IPC) 模块进行:ipcMain 和 ipcRenderer

若要创建一个窗口,请调用 BrowserWindow 类,但只能在主进程中使用 ():

const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

若要从渲染进程调用主进程,请使用 IPC 模块: 例如净化窗口模式下自定义关闭窗口功能

1. 首先由主进程向渲染进程发送消息,告诉它窗口的 id (开启了多个渲染进程);

('ready-to-show', () => {
    ('init_win_id', );
    ()
  });

 2. 在渲染进程接收 winid, 并在关闭窗口时发送给主进程

//渲染进程监听init_win_id事件(自定义),将winid赋给全局变量winid
let winid = '';

require('electron').('init_win_id', (event, message) => {
		winid = message;
})


// 关闭窗体
	function closex(){
		 
		 //渲染进程里把窗口id发给主进程

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

3. 在主进程中接收需要关闭的渲染进程

// 主进程获取winid关闭窗体
('close_window', (event, arg) => {

    //()单个窗口可以直接()
    //();
    // 1、接收渲染进程发来的窗口id
    let winid = arg;
    (winid);
    // 2、通过id找到对应的BrowserWindow对象(win、win22),调用这个对象的close()关闭对应的窗口
    (winid).close();
   
})

 主进程创建并关闭多个渲染进程

主脚本指定了运行主进程的 Electron 应用程序的入口 , 通常是 文件 , Electron 应用程序只能有一个主进程。

1. 为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,需要从 electron 包导入了 app 和 BrowserWindow 模块,

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

2.  定义一个创建新的浏览窗口的函数并将 nodeIntegration 设置为 true,将  文件加载到窗口中,

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
//注意: 设置 nodeIntegration 选项为 true 表示渲染过程中可以访问 API 
      nodeIntegration: true
    }
  })

  ('')
}

3. 调用 createWindow方法,在 electron app 第一次被初始化时创建一个新的窗口

().then(createWindow)

4.  添加一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的。

('window-all-closed', () => {
  if ( !== 'darwin') {
    ()
  }
})

5.  添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序。

('activate', () => {
  if (().length === 0) {
    createWindow()
  }
})

-------------------------------------------------------------------------------------- 创建多个窗口 -----------------------

若要创建一个窗口,请调用 BrowserWindow 类,再次创建一个 BrowserWindow 实例,但只能在主进程中使用:我们可以修改以上代码


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

//全局访问
let win
let win22

function createWindow() {
	win = new BrowserWindow({
		width: 800,
		height: 600,
		frame: false,
		webPreferences: {
			nodeIntegration: true
		}
	})

	('')
	('ready-to-show', () => {
		()
	})

	win22 = new BrowserWindow({
		width: 800,
		height: 600,
		frame: false,
		webPreferences: {
			nodeIntegration: true
		}
	})

	('')
	('ready-to-show', () => {
		()
	})

}

().then(createWindow)

('window-all-closed', () => {
	if ( !== 'darwin') {
		()
	}
})

('activate', () => {
	if (().length === 0) {
		createWindow()
	}
})

BrowserWindow 对象可调用的成员有很多,比如 id 获取唯一窗口 id,close () 成员方法关闭窗口等

-------------------------------------------------------------------------------------- 删除多个窗口 -----------------------

在主进程中将多个窗口的 id 分别发送给各自的渲染窗口,主 -> 渲染通讯 使用 BrowserWindow 实例属性 webContents 的 send () 方法实现

const {
	app,
	BrowserWindow
} = require('electron')
let win
let win22

function createWindow() {
	win = new BrowserWindow({
		width: 800,
		height: 600,
		frame: false,
		webPreferences: {
			nodeIntegration: true
		}
	})

	('')
	('ready-to-show', () => {
		('init_win_id', );
		()
	})

	win22 = new BrowserWindow({
		width: 800,
		height: 600,
		frame: false,
		webPreferences: {
			nodeIntegration: true
		}
	})

	('')
	('ready-to-show', () => {
		('init_win_id', );
		()
	})

}

().then(createWindow)

('window-all-closed', () => {
	if ( !== 'darwin') {
		()
	}
})

('activate', () => {
	if (().length === 0) {
		createWindow()
	}
})

在各自的渲染窗口中获取 winid. 并在关闭窗口事件中将之传给主进程,由主进程关闭渲染进程

以下是主进程获取到需要关闭的窗口 id 以后需要执行的操作

const {
	ipcMain
} = require('electron')
('close_window', (event, arg) => {
 let winid;
  winid = arg
  (winid);
//根据id获取 BrowserWindow实例,然后调用close()方法
  (winid).close();
 
})

关闭一个渲染进程,开启另一个渲染进程 

1. 将登录页面的窗口 id 发给主进程

let winid = '';

	require('electron').('init_win_id', (event, message) => {
		winid = message;
    })

function dologin()
{
//登录成功以后
const {ipcRenderer} = require('electron')
('dologin',winid)//winid是主进程在初始化登录页面时传过来的
}

接着在主进程中接收 winid, 关闭登录窗口,显示 qq 聊天界面

const {
	app,
	BrowserWindow
} = require('electron')
var win;
let winQQList;
function createWindow() {
	win = new BrowserWindow({
		width: 1200,
		height: 800,
		frame: false,
		show: false,
		webPreferences: {
			nodeIntegration: true,
			enableRemoteModule: true,
		}
	});

	('');

	('ready-to-show', () => {
		// 向渲染进程发消息,告诉它窗口的id
		 = ;
		('init_win_id', );
		()
	});
	
}

('dologin', () => {
        let winid = arg
		winQQList = new BrowserWindow({
			width: 300,
			height: 800,
			frame: false,
			show: false,
			webPreference: {
				nodeIntegration: true
			}

		})
		('')

		('ready-to-show', () => {
			('init_win_id', );
			()
		})


	})

转自主进程创建并关闭多个渲染进程 - imzchloe的个人空间 - OSCHINA - 中文开源技术交流社区