Electron中同一Browserwindow中多个BrowserView的z-index层级问题

介绍

Browserview是electron提供的一种作为客户端独有的api,是一种用于替代webview和iframe的技术方案,比iframe和webview有更高的操作性,但文档对于Browserview的叙述非常简单,导致在实际操作时会有些疑惑的情况。

业务场景

之前遇到的需求是这样的,公司内部目前有大概20几条业务线,都要嵌入到我的所在项目组的electron主工程内,并且要求拥有独立窗口的功能,这时问题就来了,无论是iframe还是现在火的很的微前端均无法完全满足这个要求。所以我在想我们不能用做web的思维去处理客户端项目,其实在做的过程中,要考虑的情况比纯web要多得多。这时Browserview就走入我的眼里。

小技巧

之前有同学说由于BrowserView一直处于BrowserWindow上,所以有些场景做不了,其实这里有个思路,就是能不能BrowserWindow是个空的界面,里面同时存在两个BrowserView,一个Browserview就是原来Window的内容,配合本文章,BrowserView就能愉快地玩耍了。

Browserview优势

  • 权限高
  • 主线程存活
  • 样式完全隔离

权限高

Browserview提供了webcontent的api,这个api权限就非常大,能向网页手动注入js脚本或者css样式表、提供ipcRender的对象与主线程通讯,这是原来的iframe或者webview方案所不具备的。主线程与渲染进程之间变得更高效简单,不需要通过postmessage通讯再操作,可操作空间也更加大。

后台存活

Browserview是属于主线程上的api,可以附着在各个Browserwindow上。首先它跟普通窗体有点不一样,普通窗口在关闭时,需要手动拦截关闭,不然实例就会消失。而Browserview只需要主线程上的引用还在,就可以一直活着。这里有什么好处呢?就是我们需求里面的独立窗口就可以实现了,我们只需要业务线的Browserview附着在主Browserwindow上显示,点击独立窗口时,只需把里面的Browserview取出,放到子Browserwindow上即可,同时原有的页面状态也保留下来了。

样式完全隔离

Browserview是完全独立于Browserwindow的,并不像iframe或者webview那样是一个标签,需要写在html上,样式做到了完全隔离。大家可能说iframe也是隔离,但就是之前说过web和客户端还是有些差异的,像electron里面有个css样式,就是能否拖拽的css,就有个深不可测的坑,这个是能够穿透iframe影响到主页面,情况非常怪异,也可能是我这边操作方法有问题,但最终也没能找到兼容方案,但使用了Browserview以后,这种问题就不存在了,这从根本上解决了问题,因为完全处于broserwindow和broserview完全处于两个层面。

问题来了

样式的完全隔离是可以带来非常多的好处和减少bug的,但同时也带来了一个棘手的问题,就是层级问题。在文档中介绍,browserwindow是可以 同时存在多个Browserview的,但没有明确说明broswerview的层级是如何确定的,也没有开箱即用的z-index属性。这就引发了两个问题,如何处理多个Browserview的层级是如何判断?要修改broswerview的层级要怎么办?

吐槽

这里不得不说一下,electron的官网文档还是太简单了,虽然对比react的文档算是不错了,但只介绍了api的意思,没有介绍用途,这让新手在使用时就很疑惑了,不知道什么时候该用,什么时候不该用,全靠自己摸索了,再次感叹一下vue实在是良心文档,也不怪得国内vue如此之火。

关键点

遍历文档,均没有关于Browserview的层级描述,这就很为难了,只能辩证处理,就是实践出真知。这里先说一下Browserview写入Browserview的方法,分别有两种。

  • 一是setBrowserview,介绍也是全英的,论英语对程序员的重要性,中文意思就是这个api可以把Browserview附着到指定browserwindow上,但调用这个api,一个window只能有一个browserview,重复调用的话,原有的view会被remove,只保留新的view在window内。
  • 二是addBrowserview,Replacement API for setBrowserView supporting work with multi browser views,中文意思是此方法支持写入多个browserview到Browserwindow上,我们用的也是这个api。

Browserview的z-index属性

魔鬼就藏在addBrowserview,Browserwindow对browserview的存储可以理解成是一个数组,而我们一直想找的z-index层级就在这里了,这里跟写移动端app就一样了,插入的顺序就是我们要找的z-index。换句话说,第一个插入的Browserview会被放在最底层,第二个Browserview会覆盖在前一个的browserview的前面,如此类推。

处理多个Browserview的层级

知道了z-index,就很好办了,只需要调整插入顺序就可以了。emmm,真心希望官方能直接提供一个方法,调整层级。但目前还没有,只能手动处理。方案如下

public setTopBrowserView(view:BrowserView, win:BrowserWindow): void {
  win.removeBrowserView(view);
  win.addBrowserView(view);
}

对的就是这么简单粗暴,经试验效果完美~

结语

写下来主要是因为当初自己解决时找了很久才找出来,希望各位朋友不用踩我的坑~~

首先,你需要在你的Electron应用程序安装js-web-screen-shot插件。可以使用npm安装此插件: ``` npm install js-web-screen-shot --save ``` 然后,你需要在你的Electron应用程序加载该插件。你可以在你的主进程使用require()函数: ``` const webshot = require('js-web-screen-shot'); ``` 接下来,在创建新的BrowserWindow时,你可以在其webContents加载该插件。例如: ``` const { BrowserWindow } = require('electron'); const webshot = require('js-web-screen-shot'); let win = new BrowserWindow({ width: 800, height: 600 }); win.webContents.on('dom-ready', () => { win.webContents.executeJavaScript(webshot.load()); }); ``` 在这个例子,当新的BrowserWindow的webContents准备就绪时,它会调用js-web-screen-shot的load()方法来加载该插件。现在,你就可以在新的BrowserWindow使用js-web-screen-shot插件了。例如,你可以使用它来截取屏幕截图: ``` const { BrowserWindow } = require('electron'); const webshot = require('js-web-screen-shot'); let win = new BrowserWindow({ width: 800, height: 600 }); win.webContents.on('dom-ready', () => { win.webContents.executeJavaScript(webshot.load()); win.webContents.executeJavaScript(webshot.captureScreenshot('screenshot.png')); }); ``` 在这个例子,当新的BrowserWindow的webContents准备就绪时,它会调用js-web-screen-shot的load()方法来加载该插件,然后调用它的captureScreenshot()方法来截取屏幕截图并将其保存为screenshot.png文件。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值