Electron应用被设计成跨平台的,者意味着它们可以再macOS、Windows和Linux上运行。Electron提供了与本地特性和APIs,这些特性和APIs存在于每个支持的操作系统中,但不存在于其他操作系统中。我们在前面为文件扩展名过滤器提供名称时就看到了这一点,这个名称出现在Windows中,但是macOS没有这个功能。Electron利用了这个特性,如果它是可用的,但它仍然在没有的情况下工作。
在macOS中,我们能够从窗口顶部从表格的形式显示对话框,而不是显示在窗口前面(清单4.6)。通过在配置对象之前传递对BrowserWindow实例的引用(我们已经将其存储在mainWindow中)作为dialog.showOpenDialog()的第一个参数,我们可以轻松地在Electron中创建这个UI。
图4.6 在Windows中,我们可以在不同类型的文件之间切换。
图4.7 macOS不支持在不同类型的文件之间切换,但允许我们选择filter选项定义的任何符合条件的文件。
列表4.6 在macOS中创建工作表对话框: ./app/main.js
const getFileFromUser = exports.getFileFromUser = () => { const files = dialog.showOpenDialog(mainWindow, { // 传递对BrowserWindow实例的引用对话框。showOpenDialog将导致macOS将对话框显示为从窗口标题栏向下的工作表。它对Windows和Linux没有影响。 properties: ['openFile'], filters: [ { name: 'Text Files', extensions: ['txt'] }, { name: 'Markdown Files', extensions: ['md', 'markdown'] } ] }); if (files) { return; } const file = files[0]; const content = fs.readFileSync(file).toString(); console.log(content); };通过这个简单的更改,Electron现在将Open File对话框显示为一个工作表,该工作表从传递给方法的窗口下拉,如图4.8所示。
图4.8 在macOS中,打开文件对话框现在从菜单的标题栏下拉,而不是作为应用程序窗口前面的附加窗口出现。
促进进程间通信我们已经编写了用于在主进程中选择和读取文件的所有代码。但是我们如何将文件的内容发送到渲染器进程呢?如何从UI中触发主进程中的getFileFromUser()函数?
在构建传统web应用程序时,我们必须处理类似的问题。这并不完全相同,因为所有的代码都在客户机的计算机上运行,但是考虑一下我们通常如何构建web应用程序,可以作为理解如何构造Electron应用程序的一个有用的比喻。 参见图4.9。
图4.9 Electron与传统web应用程序的职责划分
在web上,我们通常在以下两个地方编写代码: 在服务器上或在用户浏览器中运行的客户端代码。客户端代码呈现UI,它监听并处理用户操作,并更新UI以显示应用程序的当前状态。然而,我们对客户端代码所能做的事件是有限制的。正如我们在第一章中讨论的,我们不能读取数据库或文件系统。服务端代码在我们的计算机上运行,它可以访问数据库,它可以写入我们系统上的日志文件。
在传统的web应用程序中,我们通常使用HTTP之类的协议来促进客户机和服务端进程之间的通信。使用HTTP,客户机可以发送带有信息的请求,服务器接受此请求,适当地处理它,并向客户机发送响应。
在Electron应用程序中,情况有些不同。正如我们在前几章中讨论过的,Electron应用由多个进程组成: 一个主进程和一个或多个渲染进程。所有东西都在我们的计算机上运行,但是角色的分离与客户机-服务器模型类似。我们不使用HTTP在进程之间通信。相反,Electron提供了几个模块来协调主进程和渲染进程之间的通信。
我们的主进程负责与本机操作系统APIs进行连接,它负责生成渲染器进程、定义应用程序菜单和显示打开和保存对话框、注册全局快捷方式、从操作系统请求电源信息、以及更多。执行这些任务所需的模块在Electron仅在主进程中可用来实现这一点,如图4.10所示。
图4.10 Electron提供不同的模块给主进程和渲染进程。这些模块代表了Electron的代码功能,到您阅读本文时,这个列表可能还会增长,并且可能还不完整。我鼓励您访问文档以查看最新的和最棒的特性。