Electron中深度解读实现多tabs的几种方式

介绍

前一阵子写了一个Demo:electron-multi-tabs,也写了一篇文章:如何实现多tabs的模式。但其实自己对Electron的应用开发,了解也是很少。 最近看了一遍Electron 官网,发现,我Demo中使用的BrowserView 也是官网描述Deprecated的。 通过文章来了解下,几种实现多tabs的方式。

多tabs实现的方式

  • WebContentsView :(官方推介:WebContentsViews are not a part of the DOM---instead, they are created, controlled, positioned, and sized by your Main process. Using WebContentsView, you can combine and layer many pages together in the same BaseWindow.)
  • BrowserView (electron-multi-tabs使用的):(官方提示:The BrowserView class is deprecated, and replaced by the new WebContentsView class.)
  • Iframes :Iframe 在 Electron 中的行为与普通浏览器中类似。 在宿主页面的 Content Security Policy 允许范围内,一个 <iframe> 元素能在页面上显示外部网页。 要限制 <iframe> 标签中站点的功能数量,建议 使用 sandbox 属性 并且只允许您想要支持的功能。
  • WebViewWebViews are based on Chromium's WebViews and are not explicitly supported by Electron. 我们不能保证WebView API 在未来版本的 Electron 中仍然可用。 这就是为什么如果您想要使用<webview>标签,您需要在BrowserWindowwebPreferences 中设置 webviewTagtrue。(官方提示:我们不建议您使用 WebView,因为这个标签会发生剧烈的结构变化,可能会影响您应用程序的稳定性。 Consider switching to alternatives, like iframe and Electron's WebContentsView, or an architecture that avoids embedded content by design.)

多Tabs样例源码:electron-multi-tabs,效果图:

WebContentsView 官方样例

js 复制代码
    const { BaseWindow, WebContentsView } = require('electron')
    const win = new BaseWindow({ width: 800, height: 400 })

    const view1 = new WebContentsView()
    win.contentView.addChildView(view1)
    view1.webContents.loadURL('https://electronjs.org')
    view1.setBounds({ x: 0, y: 0, width: 400, height: 400 })

    const view2 = new WebContentsView()
    win.contentView.addChildView(view2)
    view2.webContents.loadURL('https://github.com/electron/electron')
    view2.setBounds({ x: 400, y: 0, width: 400, height: 400 })

简单理解下代码:创建了一个窗口,通过x坐标,把页面一分为二,左边一个页面,右边一个页面。BaseWindow的contentView对象可以添加无数个可视对象。

BrowserView 官方样例

js 复制代码
    // 在主进程中.
    const { app, BrowserView, BrowserWindow } = require('electron')

    app.whenReady().then(() => {
      const win = new BrowserWindow({ width: 800, height: 600 })

      const view = new BrowserView()
      win.setBrowserView(view)
      view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
      view.webContents.loadURL('https://electronjs.org')
    })

上述的代码,实现的逻辑跟WebContentsView差不多。 原理:通过setBounds,设置width和height为0,则内容不可见;剩下的设置为window的width和height就可以了。

Iframes

这个官方都赖得给样例代码了,因为不推介啊。

js 复制代码
    const { BrowserWindow, webFrameMain } = require('electron')

    const win = new BrowserWindow({ width: 800, height: 1500 })
    win.loadFile('你的html')

    win.webContents.on(
      'did-frame-navigate',
      (event, url, httpResponseCode, httpStatusText, isMainFrame, frameProcessId, frameRoutingId) => {
        const frame = webFrameMain.fromId(frameProcessId, frameRoutingId)
        if (frame) {
          console.log(frame.url)
        }
      }
    )
  • 从官网上了解,frame.url在主进程中是只读的,所以,变更和设置iframe的url地址,需要通过preload.js这个桥梁文件进行。
  • 上述的设计思路:一个iframe,不停的切换url,显示不同的tab的相关内容,这样的好处是,内存永远是一个页面的大小。坏处是加载很慢,而且没有keepalive。如果要一个tab一个iframe,也是可行的,但是,为了内存考虑,还是需要做限制,如上限是10个tab。

总之,不推介。

WebView

警告

Electron的 webview 标签基于 Chromium webview,后者正在经历巨大的架构变化。 这将影响 webview 的稳定性,包括呈现、导航和事件路由。 We currently recommend to not use the webview tag and to consider alternatives, like iframe, a WebContentsView, or an architecture that avoids embedded content altogether.

启用

默认情况下,Electron >= 5禁用 webview 标签。 在构造 BrowserWindow 时,需要通过设置 webviewTag webPreferences选项来启用标签。 For more information see the BrowserWindow constructor docs.

html 复制代码
   <webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>
js 复制代码
    <script>
      onload = () => {
        const webview = document.querySelector('webview')
        const indicator = document.querySelector('.indicator')

        const loadstart = () => {
          indicator.innerText = 'loading...'
        }

        const loadstop = () => {
          indicator.innerText = ''
        }

        webview.addEventListener('did-start-loading', loadstart)
        webview.addEventListener('did-stop-loading', loadstop)
      }
    </script>

使用 webview 标签将'guest'内容 (例如网页) 嵌入到您的 Electron 应用中。 Guest 内容包含在 webview 容器内。 应用中的嵌入页面可以控制外来内容的布局和重绘。

iframe不同, webview 独立于您的应用程序运行。 它拥有和你的页面不一样的权限并且所嵌入的内容和你应用之间的交互都将是异步的。 这将保证你的应用对于嵌入的内容的安全性。 ** 注意: **从宿主页上调用 webview 的方法大多数都需要对主进程进行同步调用。总之,不推介。

总结

我也是一个Electron开 发的新人,所以每走一步都会记录下来相关的一些心得。在这里跟大家一起共勉。

相关推荐
欧先生^_^6 小时前
Node.js 源码架构详解
架构·node.js
沐土Arvin8 小时前
从零开始认识 Node.js:异步非阻塞的魅力
node.js
TE-茶叶蛋8 小时前
Node.js中的洋葱模型
node.js
Q_Q196328847510 小时前
python的漫画网站管理系统
开发语言·spring boot·python·django·flask·node.js·php
outstanding木槿10 小时前
react中安装依赖时的问题 【集合】
前端·javascript·react.js·node.js
张耘华12 小时前
nosqlbooster pojie NoSQLBooster for MongoDB
node.js
Chris馒头12 小时前
Node打包报错:Error: error:0308010C:digital envelope routines::unsupported
node.js
隐含13 小时前
webpack打包,把png,jpg等文件按照在src目录结构下的存储方式打包出来。解决同一命名的图片资源在打包之后,重复命名的图片就剩下一个图片了。
前端·webpack·node.js
lightYouUp13 小时前
windows系统中下载好node无法使用npm
前端·npm·node.js
Dontla13 小时前
npm cross-env工具包介绍(跨平台环境变量设置工具)
前端·npm·node.js