likes
comments
collection
share

桌面端|Electron BrowserView 多容器管理(内附 Demo)

作者站长头像
站长
· 阅读数 8

¥¥¥源码地址¥¥¥

背景

在上文中,简单实现了一个使用BrowserView实现多标签的方案,在评论区很多小伙伴想看看源码,最近刚好有时间可以梳理下。

多标签页只是 UI 上的表象,内在逻辑是BrowserView多容器管理,所以本文重点会从容器管理这边讲解下整个的实现逻辑。

介绍

目录结构

先来看看项目依赖项:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

Demo 尽量减少技术栈来让大家更好更快理解,而不是还要理解各种框架使用。因此,除了Electron自身的框架必要依赖外,只使用了vite做渲染层脚手架。

公司项目渲染层是用的Vue3,但对我们 Demo 而言,不需要依赖任何三方框架,用Web原生实现就好。

桌面端|Electron BrowserView 多容器管理(内附 Demo)

/render UI 渲染,这个上文中写的比较多了

/src Electron 主框架

/src/container 容器管理

/src/helpers 通信交互辅助方法

/src/pages 页面管理

/src/service 通信实现

/src/window 简单的主窗口实现(本文就不涉及窗口管理,减少大家的认知成本)

运行方式

源码地址中忘了写 README,还是太仓促了,所以有同学评论说 Demo 跑不起来,这里补充下源码的运行方式。

整个项目用的是Electron推荐的yarn作为包管理工具,包安装命令如下:

yarn
桌面端|Electron BrowserView 多容器管理(内附 Demo)

由命令可知,需要开2个终端,一个运行渲染层,一个启动Electron

运行渲染层:

yarn render:dev

启动Electron

yarn start

运行结果

启动后,正常显示如下:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

登录后,点击任意需要window.open的按钮:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

出现新标签页:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

解析

下面我们来深入分析下源码,每一层都做了什么事。

渲染层

目录介绍

桌面端|Electron BrowserView 多容器管理(内附 Demo)

/tabs 存放标签页的实现,实现方式上文有讲,魔改electron-tabs实现的,本文提不再复述了。

main.ts 逻辑调用层,监听Electron通知过来的方法以及主动调用的逻辑。

代码不长,应该很好理解。

这里着重讲一下 Tab 和容器的关联关系:

以下图这个创建 Tab 监听为例:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

我们其实用的是BrowserView容器的 ID 来作为 Tab 的唯一 ID,这样来保证渲染层和容器的一致性。

新增 Tab

上文有同学评论说,不知道如何在渲染层创建一个 Tab 页。

这里解答一下,很简单:createTabOnWindow('https://www.gaoding.com') 调用createTabOnWindow方法即可。

那如何显示出一个默认的 + Tab 按钮,来新增 Tab 呢?

这个 UIelectron-tabs已经有写好的 API 了:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

但我们是BrowserView容器魔改版本,笔者项目需求也不需要 + 按钮,所以源码需要稍微调整下(github 已更新):

-. 不再使用defaultTab来设置默认点击产生的Tab(原因下文会讲)

桌面端|Electron BrowserView 多容器管理(内附 Demo)

-. 打开new-tab-button="true",让样式显示。

桌面端|Electron BrowserView 多容器管理(内附 Demo)

-. 点击 + 按钮,创建相应的 Tab 页。

tabGroup.on('click-add-button', () => {
  createTabOnWindow('https://www.gaoding.com/create-design')
})

效果如下:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

通信层

渲染层调用框架

preload.js

先来看一下preload.js

桌面端|Electron BrowserView 多容器管理(内附 Demo)

很简单,只暴露一个window.$gnb句柄,一个window.$gnb.desktop方法给前端使用。

前端调用

前端 gnb.desktop.ts 通过传类型和参数来调用框架方法:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

框架处理

方法响应处理写在DesktopService这个类中。

桌面端|Electron BrowserView 多容器管理(内附 Demo)

通过方法映射functionMap找到具体方法,进行实际调用即可。

这种设计,是GNB桌面端特性一部分,具体在跨端通信终结者|桌面端已加入全家桶🔝(还是草稿) 这篇文章中具体介绍设计理念~

框架通知渲染层

反向的,框架发生变化也需要通知到 UI 渲染层。而这里其实有一个重要的设计理念:

不仅需要框架与渲染层一对一通信的能力

还需要框架与渲染层一对多通信的能力

一对一通信比较好理解,比如需要框架侧监听 title 变化,并且修改tab的标题:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

那我们为什么需要一对多通信?本次源码并没有涉及,但这在多容器的场景下很常见:多容器页面间的状态管理,比如支付成功后,需要通知到所有打开的容器页面刷新会员信息,这里不再铺开陈述了。

框架发送

这里其实也是做了一个巧妙的解耦:

事件发送和容器接收间不产生依赖关系,而是通过GNBEventBus事件总线做中转。

容器接收代码:

BrowserWindow

桌面端|Electron BrowserView 多容器管理(内附 Demo)

BrowserView

桌面端|Electron BrowserView 多容器管理(内附 Demo)

实际发送 JS:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

可以看到,就是发送自定义事件来处理。至于是单独容器接收还是多容器接收,由传入的容器 ID 控制。

GDEventBus触发示例:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

前端监听

渲染层也是通过事件管理器GNBEventManager来监听自定义事件的触发。

GNBEventManager.shared.register() // 需要在最开始注册

gnb.desktop.ts 封装了监听方法:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

容器层

容器是用于将应用与其所有必要文件捆绑到一个运行时环境中的技术

上文一直在讲容器的概念,一般大家听的比较多的是后端概念,比如Dock容器,那在桌面端中容器是指什么呢?

在笔者理解,指的是渲染层最小运行时环境,换成Electron术语,BrowserWindowBrowserView都是容器。但窗口能实现的,其实都可以嵌套BrowserView来实现,所以BrowserView更符合容器定义。

容器封装

我们不直接使用BrowserView,而是封装一层,可以更好的做扩展及容器约束,配置初始化,建立通信机制。详见:container.ts

这里因为是为了多标签页源码而产生的 Demo,所以其实阉割掉很多能力。按我们规划上,Web 容器蓝图如下:

桌面端|Electron BrowserView 多容器管理(内附 Demo)

这是不分端的容器设计图,无论是 App 还是桌面端都是按图中的方向进行建设。

容器管理

我们有单个容器的建设后,还需要对容器进行统一管理,来保证它的生命周期以及外部规范使用。详见:index.ts

容器预加载

减少加载速度,提高用户体验,我们每使用一个容器,都会提前预加载一个新的空白容器放到内存中。

桌面端|Electron BrowserView 多容器管理(内附 Demo)

容器池

Demo 删减掉了这一部分,简单说一下,容器池主要是为了防止容器越来越多,影响到整体性能,而采用容器循环利用的方案。

业务层

容器管理、窗口管理(本文未涉及)也好,都是基建的一部分。但对业务来讲,如何去拼装容器到窗口中,形成优雅的可视化页面,这个也需要进行统一管理。

页面管理

GDTabPageContainer就是 Demo 中管理整体布局的页面容器类。详见:index.ts

它包含几部分功能:

-. 框架加载初始化

桌面端|Electron BrowserView 多容器管理(内附 Demo)

-. 管理容器布局

桌面端|Electron BrowserView 多容器管理(内附 Demo)

-. 容器持有

可以看到我们创建 Tab、切换 Tab、关闭 Tab 的方法也都是在这里面

桌面端|Electron BrowserView 多容器管理(内附 Demo)

总结

源码解析就告一段落,笔者认为管理好窗口和容器,能在性能和体验达到平衡,才是Electron的重中之重,不然不如就直接套壳Web页不就完了。按某人的话说,又不是不能用 [手动狗头] ~

问题解答

关于打包

Demo 没集成打包能力,直接用官网推荐的打包方式即可 打包教程

需要注意的是,需要把前端代码 build 下,放本地执行。不然就需要开一个本地服务来跑当前的前端渲染层代码。


感谢阅读,如果对你有用请点个赞 ❤️

桌面端|Electron BrowserView 多容器管理(内附 Demo)
转载自:https://juejin.cn/post/7299017022944395316
评论
请登录