vue3+electron开发桌面软件(4)—— 吃透electron进程通信

系列文章目录

  1. vue3+electron开发桌面软件入门与实战(0)——创建electron应用
  2. vue3+electron开发桌面软件入门与实战(1)——创建electron+vue3主体项目
  3. vue3+electron开发桌面软件入门与实战(2)——创建electron+vue3项目级集成
  4. vue3+electron开发桌面软件入门与实战(3)—— electron模块化改造+窗口位置工具+合并命令行工具
  5. 后续文章请关注专栏


前言

前面的文章,为了复现问题,我和大家一起从零重新构建的一个项目,各类代码和截图复原的也是原汁原味的构建过程,以方便引领大家顺利入门。

如今我已开源代码,需要的可私信我获取。基于此,后面的知识点和代码会挑拣重点来展示。如果你从零开始,那么按照本篇文章之前展示的代码,可以完整无误地实现效果。而按照以后的代码和讲解,可以为你打通主要关节,但因为去除部分细枝末节的代码,可能无法保证基础略薄弱的同学直接实现效果。所以如果在阅读本系列的过程中,遇到问题,建议参考源码。

这样做也有好处,前面的文章动辄大几千字,其实很影响阅读,后面的文章则会更简练。

回顾前文,我们讲解了如果简单地实现vue3+electron项目运行,如何合理地通过vite构建打包架构,对electron的一些简单优化,本篇文章将讲解electron的进程、托盘实现、项目内右键(不同于系统级右键)等实现。


一、electron的进程

electron有个很重要的概念就是进程和进程间通信,科学详细的描述请查阅官网,这里说下简单的理解:

electron分为主进程和渲染进程,主进程负责和系统级数据交互,所以需要借助nodejs或者jdk等环境,渲染进程主要负责渲染页面展示,所以需要借助浏览器环境。

正常情况下,出于安全考虑,浏览器是不可以直接操控系统底层数据的,否则咱们随便浏览个网页,就被人家植入木马或者读取电脑的关键数据了。而electron的进程通信,就是提供一种安全的通道,让浏览器环境中的渲染进程可以访问node环境中的主进程。这个通道,在electorn中被称为IPC通道。

其实我们不用特别地深究进程通信的概念,进程通信听着很麻烦,也只能说明它的实现源码可能会不太简单,但是作为一个成熟的框架,进程通信在我们的代码中使用,却极为简单。

主进程是main.js这毫无疑问,前端页面和主进程的通信需要通过预加载脚本preload.js,预加载脚本就是一个桥梁。

主进程是咋知道谁是预加载脚本的?其实前面文章已经写过了配置,只不过没有展开讲。

调用BrowserWindow方法创建窗口时,定义的参数webPreferences.preload就是预加载脚本的入口配置:

webPreferences: {
                // nodeIntegration:true,  //集成node api
                // contextIsolation:false  //关闭上下文隔离,配合nodeIntegration,可以赋予在render进程中写node代码的能力
                preload: path.resolve(__dirname, '../preload/preload.js')  //预加载的js文件
            }

注释的配置是暴力关闭上下文隔离以达到通信的目的,安全隐患太大,不建议。最好是使用preload参数配置预加载脚本的地址。

二、进程通信代码实现

按照官网讲述,electron进程通信一共分为四种模式:

  1. 渲染器进程到主进程(单向)
  2. 渲染器进程到主进程(双向)
  3. 主进程到渲染器进程
  4. 渲染器进程到渲染器进程

按照经验,第二种模式使用的场景更多,所以在我们需要通信的时候,如果无法确定应该使用哪种模式,就首选第二种模式。
我们以第二种模式和第三种模式为例:

1.渲染器进程到主进程(双向)

网络上大部分教程都是借鉴或者直接把官网文档抄过来,所以导致讲述流程都是正向的,就像做数学题一样,我事先已经知道了参考答案,所以从头给你讲,听完你觉得好有道理。下一道类似习题发现还是不会。

官网这样讲解没有问题,因为它是作为参考文档,方便我们在遇到问题的时候去查阅。但我们真正去学的时候,这样会很累。

有时候我们需要从问题反推,才能复现我们真正遇到问题的场景。

我们经常遇到的一种场景是:页面上有个操作按钮,点击按钮后,通过node操作系统。这就涉及如何把操作指令从渲染进程发送到主进程。

我们的起点在页面按钮上,所以点击按钮后应该有个方法去通知主进程,形如:

 myApi.handleGetProgressArgv().then((value)=>{
    console.log(value)
  })

通过这个方法,我们就能通知主进程你该调用某个特定函数了!!!

  • myApi:自定义的对象,需要在预加载js中定义,后续介绍。
  • handleGetProgressArgv:自定义的函数,需要在预加载js中定义,后续介绍。

可以看到,这个方法完全是自定义的一个方法,如果不作任何操作,系统是绝对不认识的。所以我们需要给我们想要的方法一个定义,让系统知道,这个渲染器里调用的方法,我定义的。

渲染页面调用主进程是有危险的,所以这脏活累活肯定得桥梁preload.js来做:

const handleGetProgressArgv=async () => {
    let files = await ipcRenderer.invoke('get-progress-files')
    console.log('files',files)
    return files // 返回结果
}

/**
 * 暴露给前端windows对象,windows对象的属性可以用windows.myApi调用或者直接简写为myApi调用
 * */
contextBridge.exposeInMainWorld('myApi', {
    handleGetProgressArgv
})

preload.js中定义函数并且把它通过exposeInMainWorld暴露,页面就能自动找到这个函数了。

现在页面通过按钮,能直接给preload.js发指令调用某个函数了,但是preload.js支持的node模块是很有限的,它毕竟和渲染页面不清不楚的,不太安(干)全(净)啊。

所以预加载页面拿到这个指令后,还得继续向上报告。这就是下面这行代码做的事。

ipcRenderer.invoke('get-progress-files','hhhhhhhhhhhh')

这句代码告诉主进程,我这有个方法叫“get-progress-files”,参数是‘hhhhhhhhhhhh’,大哥帮忙接受下。

可预加载里方法多了去了,主进程怎么分辨出来哪个函数做什么?所以主进程自己也搞了一个api叫‘handle’,用来和预加载里的函数一一对应:

ipcMain.handle('get-progress-files',(event,msg)=>{

	……省略一堆代码
   console.log(msg) //这里会打印一串hhhhhhhhhhhh
    return 'main'
})

主进程又可以返回一直值:‘main’,这个值会被预加载里对应的函数接收,我们赋值给files,形如:

let files = await ipcRenderer.invoke('get-progress-files')

然后预加载返回的值,又能被页面中的方法“myApi.handleGetProgressArgv”接收,至此,一个指令带着参数,由页面开始,流转一圈后,又带着返回值回到页面了。

因为这种方式,可以说是把流程走了一个来回,所以应用范围最广。

2.主进程到渲染器进程

我们在项目中还经常遇到一种情况,工具栏需要控制渲染器的行为,比如返回登录页、打开调试工具等等。如图:
在这里插入图片描述
这就是典型的主进程到渲染器进程通信。主进程发送指令,控制渲染器进行相应操作。

原理其实和上面双向通信类似。

指令从主进程开始,所以在点击工具栏按钮时,发送指令:

{
                label: '文件',
                submenu: [
                    {
                        label: '返回首页',
                        accelerator: 'CmdOrCtrl+W',
                        click:() => this.win.webContents.send('go-page', 'login'), //主进程主动通信到渲染进程
                    },
                    {
                        label: '退出',
                        accelerator: 'CmdOrCtrl+Q',
                        click() {
                            app.quit()
                        }
                    }
                ]
            },

当点击【返回首页】时,会告诉预加载脚本,我给你发了个函数:

预加载脚本为了能正确接到对应的函数,需要对应着接一下,不同于上面的invoke接口,这次需要用“on”来接住:

const handleGoPage=(callback) => ipcRenderer.on('go-page', callback) //监听主进程事件

预加载脚本接住后想告诉页面主进程又来活了,就只能继续暴露这个函数:

contextBridge.exposeInMainWorld('myApi', {
    handleGoPage,
    handleGetProgressArgv
})

页面上找个恰当的时机,我放在了App.vue中,调用这个函数:

myApi.handleGoPage((event, value) => {
  router.push(value)
  // event.sender.send('counter-value', value)  //将回复结果发回主进程
})

这样,就完成了主进程传达的指令。

3.进程通信思考

另外两种进程通信方式这里不再赘述。

通过这两种通信方式,不难总结规律:

主进程 <——> 预加载脚本 <——> 渲染页面

进程通信就是这三者之间互相调用,通过预加载脚本这个桥梁,让主进程和渲染进程可以互相发送指令。进程通信涉及的api对于新接触的同学来说,可能比较陌生,不过理解了这个规律,这些api也不过是成对出现的发送和接收接口而已。


总结

这篇文章用相对通俗的语言解释了electron的进程通信,并为其中的两种编写示例代码。如果能够理解主进程、预加载脚本、渲染页面之间的关系,其实不管有多少种进程通信方式,也不过是多查阅几个api而已。

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
首先,VueElectron是两个不同的技术,Vue是一种用于构建用户界面的JavaScript框架,而Electron是一种用于构建跨平台桌面应用程序的框架,它使用Web技术(HTML,CSS和JavaScript)来构建应用程序。 如果你是0基础入门,首先需要学习VueElectron的基础知识。以下是一些学习资源: Vue: - Vue官方文档:https://v3.vuejs.org/guide/introduction.html - Vue Mastery:https://www.vuemastery.com/ - Codecademy:https://www.codecademy.com/learn/learn-vue Electron: - Electron官方文档:https://www.electronjs.org/docs - Udemy:https://www.udemy.com/course/electron-from-scratch/ - Pluralsight:https://www.pluralsight.com/courses/electron-fundamentals 一旦你学习了VueElectron的基础知识,你可以开始构建你的第一个Vue3+Electron桌面应用程序。以下是一些步骤: 1. 安装Vue CLI和Electron:使用npm安装Vue CLI和Electron。 ``` npm install -g @vue/cli npm install -g electron ``` 2. 创建Vue项目:使用Vue CLI创建一个新的Vue项目。 ``` vue create my-electron-app ``` 3. 添加Electron支持:在Vue项目中安装electron-builder。 ``` cd my-electron-app vue add electron-builder ``` 4. 编写代码:你现在可以开始编写VueElectron代码了。你可以在Vue组件中使用Electron API来访问系统资源。你可以在Electron主进程中编写Node.js代码以访问底层系统资源。 以上是一个简单的介绍,希望对你有所帮助。祝你好运!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中二少年学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值