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的引用都是跟版本挂钩了,大家如果一意孤行还要用使用不推荐的方式来使用原生能力的话,那么配置就按照上面的来做即可了。

相关推荐
高兴蛋炒饭5 小时前
RouYi-Vue框架,环境搭建以及使用
前端·javascript·vue.js
ᥬ 小月亮5 小时前
Vue中接入萤石等直播视频(更新中ing)
前端·javascript·vue.js
夜斗(dou)6 小时前
node.js文件压缩包解析,反馈解析进度,解析后的文件字节正常
开发语言·javascript·node.js
恩爸编程6 小时前
纯 HTML+CSS+JS 实现一个炫酷的圣诞树动画特效
javascript·css·html·圣诞树·圣诞树特效·圣诞树js实现·纯js实现圣诞树
神雕杨6 小时前
node js 过滤空白行
开发语言·前端·javascript
艾斯特_7 小时前
前端代码装饰器的介绍及应用
前端·javascript
Sokachlh7 小时前
【elementplus】中文模式
前端·javascript
Cshaosun7 小时前
js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)
开发语言·javascript·es6
轻口味8 小时前
【每日学点鸿蒙知识】webview性能优化、taskpool、热更新、Navigation问题、调试时每次都卸载重装问题
javascript·list·harmonyos
涔溪9 小时前
如何在Express.js中定义多个HTTP方法?
javascript·http·express