2. Electron窗口开发实战指南

1 前言

前一章我们已经学习了如何使用模板来创建一个窗口,并顺带讲解了一下这个模板中的代码结构。

但总的来说,前面整个章节都只是在做准备工作而已。而从本章开始,我们就正式踏入学习Electron核心内容的旅程了。

既然这个框架是做GUI软件的,那窗口自然就是最重要的,所以我们本章就以窗口开始学习。

2 了解窗口

首先我们需要明白的一个点就是:窗口不是应用程序

正如前面章节从代码中看到的那样,app这个实例代表当前这个应用程序。

但只有它还不够,因为没有窗口的命令行程序(也称CLI``,Command Line Interface,命令行接口)也是程序,只不过两者的交互方式不一样而已。

窗口只是应用程序的一种交互方式,也就是我们常常能看到的GUIGraphical User Interface,图形用户接口)。

所以一个应用程序既可以没有窗口,也可以创建多个窗口,只不过我们看到一个窗口的应用程序居多,因为其开发起来更加简单、使用起来更加简洁,仅此而已,

窗口就像一块画布,你是可以任意绘制的,不同框架提供的绘制方式并不相同。

对于Electron框架来说,窗口就是通过htmljscss这三大前端基石来完成的,所以学习本系列的前提是,你得学会这三个基础。

一个传统化的标准窗口程序一般会包含以下五个部分:

  • 标题栏:即窗口最上面、包含最大最小化的那一行,还可以用于鼠标拖动窗口。
  • 菜单栏:存放各种功能命令,一般在标题栏下方
  • 工具栏:存放各种常用功能,一般在菜单栏下方,但在现代应用程序中已经很少见到了(word这种软件中你也还是能看到)。
  • 内容区域:窗口正中间,工具栏的下方,这个区域就是我们可以发挥想象力的地方了,你可以在其中存放任何东西。
  • 状态栏:窗口最下面,也就是内容区域的下面,用于显示一些状态信息的。

比如windows系统自带的记事本程序:

image-20230922091431453

比如wps的工具栏:

image-20230922091555689

但这也仅仅只是传统的窗口模式,现在的很多应用程序已经逐渐开始模糊了各个区域的边界。

比如像上面看到的记事本、wps,它们的标题栏除了最基本的功能外,还多了一个标签页的功能,更加节约空间的同时也会更加美观。

但想要做到这一点并不容易,因为这超出了传统的窗口模式,系统本身的窗口是不支持的。

所以这就需要我们进行定制!

什么是定制呢?

前面我们提到了,按照传统模式来说,其实也就只有中间的内容区域可以任由我们自由发挥,其它区域都是有自己特定格式的,你并不能随意改动。

而定制的方法就是:禁用其它四个区域,只保留中间的内容区域。

然后重点就来了,由于内容区域我们是可以任意绘制的,所以我们就可以通过在内容区域自己绘制标题栏、菜单栏等等,从而实现整个应用程序高度自定义化!

3 了解BrowserWindow

有了前面的基础,我们就可以正式来聊聊Electron中的窗口了,Electron框架是通过BrowserWindow类来创建一个窗口的,所以我们主要就是来看看这个类到底是怎么用的!

官方文档为:BrowserWindow

学会看官方文档是个好习惯,因为我现在讲的东西可能一年后就过时了,但官方文档会一直保持在最新的状态。

image-20230922093349762

虽然中文翻译过来看起来可能有点奇怪,但基本还是能看懂它的意思。

其官方文档的前部分作用基本就是我上图所标注的那样。

从这里我们就能看到更多的内容,比如,这个窗口类不仅仅可以用loadFile加载本地的html文件作为窗口样式,也可以用函数loadURL这个函数加载网页作为窗口。

还有前面用的在app.on('ready', createWindow);这里也提到了,就是要等这个事件之后才能创建窗口。

事件一般有两种使用方式,一种就是最开始用的,直接将事件封装成为了一个函数:app.whenReady()

但更常用的还是用通用函数on,然后第一个参数传入你想要等待的事件即可,而第二个参数就是你想要在这个事件发生后要执行的函数。

由于这个类是Electron中的核心类,里面的东西非常之多。我也不可能一个一个挨着说完,所以这里只给大家稍微理一理即可。

image-20230922094422850

从右边的目录看起,class BrowserWindow前面的内容都是官方将其最常见的用法写出来,教我们怎么用。这个后面我也会聊聊。

然后class BrowserWindow后面的内容才是真正在开始介绍这个类中有哪些东西。

不过由于它的内容太多了!所以我这里也只能分类聊聊他们的区别,然后后面再挑几个常用的讲一讲。

首先是这个带new的,这是在实例化一个对象。

image-20230922094813303

实例化对象很多时候都需要很多选项,比如前面我们填的窗口宽高,你都可以在这里找到,除此之外你还能看到相当多的其它属性,可以自己试一试。

然后下面的就是事件:

image-20230922095228575

用法如上图,最简单的就是举个例子:

//省略创建窗口win实例的过程
win.on('page-title-updated',(event,title,explicitSet)=>{

})

第二、三个你可能知道,一个是字符串(string),一个是布尔(boolean),那么第一个事件(Event)是什么鬼呢?

不知道没关系,你可以在代码中直接用函数console.log函数将它打印一下就行了,这就是一个对象而已。

其它事件的使用方法也是同理,后面如果用到了会再提。

然后是静态方法:

image-20230922095705682

静态方法比前面的实例方法用起来要简单一点,因为你不用创建窗口就可以直接使用这些方法,就像上面官方文档所示的那样:

let wins=BrowserWindow.getAllWindows(); //获取当前所有窗口,返回值是一个窗口数组

官方文档这方面已经介绍的很详细了,我就不再多说了。

唯一你可能觉得疑惑的就是,这些返回值都是什么意思?

其实不用管它,凡是这种不知道什么东西的类型,一般都是自定义对象,你只要用console.log函数打印一下它就知道它里面都有写什么东西了。

接下来是实例属性:

image-20230922100136265

只要带有实例二字的,就是需要你先创建好一个窗口才能使用的东西,只能通过创建好的这个实例进行调用。

实例属性就是我们创建的这个窗口上有哪些东西,比如这里的webContents,又是一个对象,具体这个对象有哪些东西,可以点官方所示文档进去查看。

还有这里的id,就是用来标识当前窗口的一个数字,后面跟了只读两个字,就意味着你不能更改它,但你能读取它:

console.log(win.id); //打印窗口的id

最后就是实例方法:

image-20230922100951189

当你创建了窗口之后,你就可以通过这些函数来控制这个窗口的行为,比如这里的destroy()方法,就可以用来强制关闭这个窗口。

同时注意其下面的备注信息,出现了触发这两个字,只要出现了触发,就意味着它现在正在谈论的是事件,所以前面提到的closedcloseunloadbeforeunload这几个单词都是指的事件名。

这是中文翻译的问题,如果你看英文版本,就不会出现这种疑惑了:

image-20230922101524211

英文版本明确指出这是事件,所以一般来说,还是推荐大家阅读英文版本的,如果看不懂,可以使用网页翻译对照着看。

不用非得将英语学的有多好,我英语也不好,但编程相关的常见单词其实也就百来个,你多见见、多翻译翻译,自然就能看懂了,大部分都是很简单的单词,也很少会出现四六级、高考那种长难句,不会的直接上翻译即可。

至此,我们就大致将这个窗口类从总体上观览了一遍,下面开始实战!

4 优雅显示窗口

既然官方都认为这是大家遇到的最多的问题,将其从文档中写出来了,那也没什么可说的,我就再多解释几句、实战一些。

之所以会出现这个问题,主要是创建窗口、加载页面并不是同时进行的。

正如前一章节我们看到其自动生成的代码中(也就是createWindow函数中的代码,我做了部分删减、翻译):

// 创建窗口
const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    show:false //默认隐藏窗口
});
// 加载页面
mainWindow.loadFile(path.join(__dirname,'index.html'));

这就会导致,当窗口创建好的时候,你的页面还没加载后,就会在启动的时候出现瞬间的白屏。

我本来是准备截图的,可惜太快了,截不到,你可以自己运行试一试,确实是由一瞬间的白屏。

如果你的页面很复杂,可能白屏的事件就会更长,用户体验就不好。

所以官方就给出了两种解决方案。

第一种是针对页面并不复杂的、启动本身就很快的程序,你可以让窗口默认不显示,等页面加载完成后再显示,不就看不到加载那一刻的白屏了嘛!

  // 创建窗口
  const mainWindow = new BrowserWindow({
    width: 800,
作者:余识
全部文章:0
会员文章:0
总阅读量:0
c/c++pythonrustJavaScriptwindowslinux