electron大多数都是来开发桌面端的应用,个人对它的工作流进行了总结。 首先我们打开某个App,window就会打开主进程,然后由win渲染界面,随之用户会与应用发生交互,首先会被渲染进程捕捉到,然后传递给主进程,主进程去做相应的逻辑处理,主进程调用原生的api完成操作。 electron分为主进程和渲染进程,主进程可以理解为是main.js文件,渲染进程是ipcRender文件。 主进程,
主进程想和渲染进程通信,需要通过preload预加载脚本,但不通过预加载脚本也可以实现,只不过不安全。预加载脚本可以实现与主进程的通信,同时也可以实现与渲染进行的通信。
从渲染器进程到主进程的异步通信 ipcRenderer
1. 在主进程中通过ipcMain.on('事件名',()=>{相应的逻辑处理})监听ipcRenderder.send('事件名')发送的指令。
预加载脚本和渲染脚本中都有window,但是它里面的window是各自隔离开的,但也可以通过方法使他们俩成为一个window对象。
// 通过contextBridge.exposeInMainWorld把它里面定义的方法或变量暴露出去,使渲染进程可以使用
预加载里面写暴露方法,在ipcRenderer中通过window.obj使用
contextBridge.exposeInMainWorld('obj',{
a:'333'
})
渲染进程可以通过window.obj拿到{a: '333'}这个对象,这样他俩之间就可以共享数据,并与进程安全的通信。 默认情况下,preload.js里是用不了require()模块的,但可以进行更改。
总结渲染进程与主进程通信:在preload中暴露想使用的通信方法,preload中暴露出来的方法在渲染进程中对dom行操作,主进程监听到事件触发以后,就执行对应事件里的逻辑
从主进程到渲染进程的异步通信 ipcMain
例子:
-
如果想通过网页菜单做某些事情,可以在主进程创建菜单,(由于一个项目可以有多个渲染进程,所以要把当前菜单控制的具体渲染进程传进去,渲染进程指的是创建出来的窗口
new BrowserWindow()对象)。 -
菜单项结构定义类似于
option,当点击某一个菜单,触发事件,可以通过传进来的渲染进程的win.webCOntents.send('事件名')发布指令,同时也可以传递参数,会被ipcRender.on接收到。 -
发布指令之后,预加载脚本里的
ipcRederer.on()就可以监听到,为了安全起见,预加载脚本里都是暴露方法,在渲染进程中使用,所以,可以对暴露的方法传递calbback,把会用到的参数通过callback返回出去. -
从而在渲染进程中实现对
dom的操作。
双向通信
方式:就是把上面的两种方式进行结合。 例子:点击按钮,向主进程发起进攻,主进程接收到信息之后,给予反馈。
index.html文件
<body>
<button id='btn'>双向通讯</button>
</body>
<script src='renderer.js'></script>
渲染进程 renderer.js文件
window.addEventListener('DOMContentLoaded', () => {
const el = doucment.getElementById( 'btn' );
el.addEventlistener( 'click', () => {
// 触发预加载文件暴露出来的事件
window.api.jingong( );
})
})
预加载文件 preload.js
const { ContentBridge, ipcRenderer } = require( 'electron' );
// 暴露事件,与渲染进程共享方法
ContentBridge.exposeInMainWorld( 'api', {
jingong: () => {
ipcRenderer.send( 'saveFile' );
}
})
// 监听主进程给予的反馈
ipcRenderer.on( 'message', (event, arg) => {
console.log( arg ); //已经收到保存文件指令!!!
} )
主进程文件 main.js
const { BrowerWindow, app} = require( 'electron' );
function createWindow(){
const mainWindow = new BrowserWindow({
window: 500,
height: 500,
webPreferences:{
preload: path.resolve(__dirname, 'preload.js'),
}
});
mainWindow.loadFile( path.resolve(__dirname, 'index.html') )
}
// 初始化窗口
app.whenReady().then(() => {
createWindow();
})
// 监听ipcRenderer发出的saveFile事件
ipcMain.on('saveFile', (event) => {
// 给予反馈
BrowserWindow.fromWebContents( event.sender ).send('message', '已经收到保存文件指令!!!')
})