Electron 的通讯机制
Electron 在运行时分为主进程和渲染器进程(渲染进程),主进程可以用NodeJS
的 api,渲染进程可以用浏览器的 api
两者之间需要通过 Electron 提供的 api 来通讯
渲染进程
首先需要在渲染进程设置一个监听器,用来监听主进程发来的消息
然后主动发送一个消息给主进程
代码语言:javascript复制// 监听器
ipcRenderer.on('mainSend', (event, message) => {
console.log('主进程发来的消息', message)
})
// 在合适的地方发送给主进程,比如按钮点击事件中
button.onclick = function() {
ipcRenderer.send('rendererSend', 'xxx')
}
主进程
接下来是主进程中,需要创建一个监听器,用来监听渲染进程发过来的消息
代码语言:javascript复制ipcMain.on('rendererSend', (event, path) => {
// 这里是主进程的处理,比如渲染进程发来的是一个文件路径
// 主进程可以调用 NodeJs 的 api
fs.unlink(path)
// 删除后在告诉渲染进程已经删掉了
event.sender.send('mainSend', `${path} 已删除`)
})
至此,渲染进程的监听器mainSend
会接收到消息,xxx 已删除
带来的问题
个人感觉这种写法比较难受,因为我加一个通讯,就得写一遍上述内容
最少的情况也是主进程和渲染进程各要写一个,最后会有大量的on
、send
electron-vue-event-manager
于是解决方案出现了,electron-vue-event-manager
是个基于electron-vue
的事件管理器
可以让你在任意地方创建监听器,在任意地方触发它(发起广播)
它能解决如下问题
- 主进程与渲染进程通信
- 渲染进程自身的通信 (同一窗口内
Vue
组件之间) - 渲染进程与其他渲染进程通信 (不同窗口之间)
初始化
既然每个通信都需要一个on
和一个send
,那其实我只需创建一次
再通过不同的参数区分具体是什么通讯,不就解决了每种通讯要创建一个on
和send
的问题了
electron-vue-event-manager
的解决方案正是如此,在主进程和渲染进程中调用各自的初始化函数
// 主线程 (需要把所有创建的窗口传进去)
EventManager.Instance().mainInit([
{
// 创建的窗口,类型 BrowserWindow
window: window1,
// 类型,唯一标示
type: 'window1'
},
{
window: window2,
type: 'window2'
}
])
// 渲染进程
EventManager.Instance().rendererInit()
监听器
然后就可以在任何地方写一个监听器,比如下面这个是在渲染进程中,Vue
的某个页面的created
生命周期中
// Window2 添加监听事件
EventManager.Instance().addEventListener<string>(
// 事件类型 (string)
EventType.Window1SendMessage,
// 接收到广播后的回调函数
(window1Message) => {
this.message = window1Message
console.log('接收到来自 Window1 的消息:', window1Message)
}
)
广播
广播指的是调用监听器,监听器可以有多个,相当于收音机,所以调用这个动作叫做广播
以下是在另一个渲染进程中
代码语言:javascript复制// Window1 进行广播
EventManager.Instance().broadcast<string>(
// 事件类型 (string)
EventType.Window1SendMessage,
// 参数 (输入框内容)
this.inputValue
)
实际应用
以上的代码实际应用如下图,你可以从Window1
发送消息给Window2
也可以在Vue
组件之间传递
网络请求
除了跨窗口、跨组件通信之外,还有网络请求是需要封装的
因为渲染进程是个浏览器窗口,发起网络请求也就会有跨域问题
所以你需要先让渲染进程把请求相关的数据发给主进程,再由主进程发起网络请求,拿到数据后发回渲染进程
在electron-vue-event-manager
基于axios
封装好了一个方法,可以在任何地方调用即可发起网络请求
EventManager.Instance().sendRequest({
url: 'Request URL',
method: 'POST'
}).then(data => {
console.log(data)
})
// EventManager.Instance().sendRequest(options) === axios(options).then(response => response.data)
使用
当前
1.0.0
之前为自用版,因为还有很多没完善
目前能做到像上述的功能一样,但可能存在问题,谨慎使用
你可以在 Github、Npmjs 获取到更多信息