Electron[5] 渲染进程和主进程

1 进程

Electron里头的进程分为渲染进程和主进程。简单理解:

  1. main.js就是主进程
  2. 每个页面就是渲染进程
  3. 一个Electron应用仅有一个主进程,可以有多个渲染进程
    上面的这些概念很重要,不展开细讲。

2 进程职责

主进程是用来实现应用的基础功能,包括跟底层的系统交互等。渲染进程是用来实现具体每个页面的功能。

那么当渲染进程需要跟系统底层进行交互的时候,怎么处理呢?目前有两种方式:

  1. 在渲染进程里头直接引用支持跟底层进行交互的包,然后直接实现跟底层的交互(十分不推荐)
  2. 渲染进程将事件委托给主进程,让主进程来完成。(推荐)
  3. 事件委托是通过事件监听和触发来实现的。

3 渲染进程与Native API

虽然上面说了,不建议渲染进程直接调用Native API,但是还是要说下,渲染进程如何实现直接调用底层API。

之所以不建议渲染进程直接调用Native API是因为,渲染进程调用原生能力,其实是从主进程同步过来的,那么在应用的使用过程,就要不断的实现主进程和渲染进程之间的原生能力载体的状态同步,这个同步是十分耗费宿主机资源的。

3.1保存文件

下面的案例是讲解下如何通过渲染进程直接调用原生API。

3.1.1 渲染进程页面

先用h5画出包含有一个文本框和用来保存的按钮。

源码如下:

html 复制代码
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>electron从入门到精通</title>
</head>
<body> 
    <button type="button" id="saveBtn">保存文件</button>
    <textarea id="textArea" style="position:absolute;top:60px;bottom:0;left:0;right:0;"></textarea>
<script src="./test.js"></script>
</body>
</html>

然后test.js的源码如下:

javascript 复制代码
const { dialog } = require('@electron/remote')
//引入fs模块
var fs = require('fs')
//获取文本框的dom 
var textAreaDom = document.querySelector('#textArea')
var saveBtn = document.getElementById('saveBtn')

// 文件保存路径,第一保存后,就缓存起来
var currentPath = null
saveBtn.addEventListener('click',function(){
    if (currentPath) {
        writeFile(currentPath)
    } else {
    	// 调用native api实现文件保存
        dialog.showSaveDialog({properties:['showOverwriteConfirmation']}).then(({canceled,filePath})=>{
            if (!canceled) {
                writeFile(filePath)
                currentPath = filePath
            }
        })
    }
    
})
function writeFile(path,){
    fs.writeFileSync(path, textAreaDom.value)

}

到这边要停下来下,缓一缓捋一捋。

首先,我们需要在渲染进程里头引用node的包,fs包,其次,还用到了remote的依赖包。因此还需要做如下操作:

  • 安装@electron/remote,版本:2.0.12
bash 复制代码
npm install @electron/remote@2.0.12
  • 调整渲染进程窗口的创建配置。创建窗口是在main.js里实现的,下面直接附上整个main.js的文件:
javascript 复制代码
		// main.js
	const { app, BrowserWindow} = require('electron')
	const path = require('path')
  
	// *************************1.引入remote模块******************************
	const remote = require("@electron/remote/main");
	remote.initialize();

	function createWindow () {
		const mainWindow = new BrowserWindow({
			width: 800,
			height: 600,
			webPreferences:{
				//  渲染进程 开启node模块,使得JS中可以使用node的model
				nodeIntegration:true,
				// 开启 remote 模块
				enableBlinkFeatures:true,
				// 控制上下文隔离
				contextIsolation:false,
				//由于安全问题,remote模块默认关闭
				enableRemoteModule: true,//开启remote模块
				//关闭web权限检查,允许跨域
				webSecurity: false,
			}
		})

		mainWindow.loadFile('./src/index.html')
			// 默认打开调试工具
		mainWindow.webContents.openDevTools()
		// ********2.启用remote模块,渲染进程就可以使用主程序模块********************
		remote.enable(mainWindow.webContents);  
	}
	
	app.whenReady().then(() => {
	  createWindow()
	
	  app.on('activate', () => {
	    if (BrowserWindow.getAllWindows().length === 0) {
	      createWindow()
	    }
	  })
	})
	
	app.on('window-all-closed', () => {
	  if (process.platform !== 'darwin') {
	    app.quit()
	  }
	})

至此,源码分享就结束了。

4 源码解释

4.1 test.js和Electron的原生能力

上面主要麻烦的就是test.js里头的dialog的使用。这个调用的是原生能力的弹窗,其实像原生能力的使用,不知道都觉得很麻烦,但是,如果知道了,就不难,下面附上原生能力的工具字典:
app | Electron

4.2 remote模块

不同版本的Electron使用的remote是不一样的,main.js里头关于remote的配置,以及渲染进程里头的remote的引用都是跟版本挂钩了,大家如果一意孤行还要用使用不推荐的方式来使用原生能力的话,那么配置就按照上面的来做即可了。

相关推荐
十一吖i1 小时前
vue3表格显示隐藏列全屏拖动功能
前端·javascript·vue.js
徐同保3 小时前
tailwindcss暗色主题切换
开发语言·前端·javascript
生莫甲鲁浪戴3 小时前
Android Studio新手开发第二十七天
前端·javascript·android studio
细节控菜鸡5 小时前
【2025最新】ArcGIS for JS 实现随着时间变化而变化的热力图
开发语言·javascript·arcgis
拉不动的猪6 小时前
h5后台切换检测利用visibilitychange的缺点分析
前端·javascript·面试
桃子不吃李子6 小时前
nextTick的使用
前端·javascript·vue.js
Devil枫8 小时前
HarmonyOS鸿蒙应用:仓颉语言与JavaScript核心差异深度解析
开发语言·javascript·ecmascript
惺忪97988 小时前
回调函数的概念
开发语言·前端·javascript
前端 贾公子8 小时前
Element Plus组件v-loading在el-dialog组件上使用无效
前端·javascript·vue.js
天外飞雨道沧桑8 小时前
JS/CSS实现元素样式隔离
前端·javascript·css·人工智能·ai