在本节中,我们将了解在Electron中创建任何应用程序时的一些基本模块;这些模块多种多样,使我们能够轻松地进行进程通信,创建操作系统的本地菜单。
为了利用Electron模块,以及任何第三方或Node模块,不仅在主流程中,而且在渲染或网页流程中,我们需要为该流程启用与Node的集成。
Node与Electron的集成是指能够在渲染过程中访问Node.js资源;有了这一点,我们可以从网页上以一种简单直接的方式使用Electron API。
Electron中默认禁用与node的集成,对于最终或生产应用程序,建议将其禁用作为安全措施。
能够从网页中使用Node(并且能够导入和使用任何包),对于执行几个操作至关重要,总之,例如我们将在下一节中看到的流程之间的通信;为了实现与Node的集成,我们提出:
index.js
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
与JavaScript一样,事件是在某些时间执行的通知在应用程序的生命周期中,在这个机会中,我们谈论特定于应用程序而不是用户触发的事件。在Electron中,我们有许多类型的在关闭窗口、加载网页,当停止页面加载等, 需要注意的是,所有这些事件都发生在主过程中;因为,这是加载不同网页的地方。
我们在Electron有两种类型的事件:
作为对读者的建议,请查看之前的每个链接,以便您可以了解我们在Electron举办的活动,之前的文档有西班牙语和英语两种版本。最后,从应用程序发出的事件看起来像:index.js
const { app, BrowserWindow } = require("electron");
function createWindow() {
let win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
},
});
win.loadFile("index.html");
win.webContents.openDevTools();
//无论网页加载成功或者失败都会调用,航完成时触发,即选项卡的旋转器将停止旋转,并指派onload事件后。
win.webContents.on("did-finish-load", () => {
console.log("did-finish-load");
});
//在网页加载失败的时候调用,在这里我们可以重新加载网页,或者可以自定义错误404页面
win.webContents.on("did-fail-load", () => {
console.log("did-fail-load");
});
}
app.whenReady().then(createWindow);
//所有的窗口都关闭的时候触发
app.on("window-all-closed", () => {
console.log("window-all-closed");
});
在许多场景中,我们需要同时与两个进程进行通信,即当主进程和/或渲染进程中发生事件时,我们可以随时发送所述消息以执行特定操作;能够通过进程之间的事件发送消息对于执行只能在其中一方执行但我们需要与另一方通信的操作特别有用;例如:
简言之,就像任何其他范式一样,例如基于web应用程序使用的客户端和服务器的范式,直接或间接地传达所涉及的层或过程是至关重要的,我们将详细学习如何进行这些过程。
在Electron,我们有一个单一的主流程和一个或多个渲染或网页流程;两者之间的通信是通过几个模块完成的:
让我们在实践中分析每一个。
为了从主流程向网页发送消息,我们有以下功能:
<window>.webContents.send(<EVENT>,<VALUE>)
其中,
const { ipcRenderer } = require('electron')
ipcRenderer.on(<EVENT>, (event, arg) => {
// TO DO
});
例如,从主进程中可以看出:
index.js
function createWindow() {
//省略前面的代码
setTimeout(()=> win.webContents.send('message','Hello world'),1000)
}
index.html
const { ipcRenderer } = require('electron')
ipcRenderer.on('message', (event, arg) => {
alert("Mensaje recibido desde el proceso principal: " + arg);
});
为了能够从渲染过程或网页发送消息,我们非常简单,只需从网页传递消息:
const { ipcRenderer } = require('electron')
ipcRenderer.send('message', <DATA>)
从主进程来看,我们有一个回调事件:
const {ipcMain} = require('electron')
ipcMain.on('message',(event, arg) => {
//TO DO
})
其中应用了相同的逻辑,其中我们定义了一个事件和值,这是完全可选的。它与主进程和渲染进程之间的通信方案相同;你可以放一个console.log(),你会在终端看到消息。
有很多方法可以将Electron事件与两个进程之间的消息一起使用,但一种非常常用的组合是,当(例如)加载页面以初始化页面时,在进程之间发送消息;是一种广泛使用的组合:index.js
//无论网页加载成功或者失败都会调用,航完成时触发,即选项卡的旋转器将停止旋转,并指派onload事件后。
win.webContents.on("did-finish-load", () => {
console.log("did-finish-load");
win.webContents.send("data-from-server", { key: "value" });
});
index.html
ipcRenderer.on('data-from-server',(event, data)=>{
// TO DO
})
从网页上,发送消息也是很常见的;作为一个网页,我们在这里的优势是,我们可以将JavaScript事件与Electron消息结合使用,一般来说,还可以使用我们想要的任何其他类型的集成,例如与Vue、Angular或React等框架结合使用;但是,我们稍后会看到。
在本节中,我们将使用Electron中的菜单;有了它们,我们可以在操作系统中创建本机菜单。
菜单结构只不过是一个具有预定义结构的对象阵列;我们可以在菜单中定义两种类型的选项,个性化和具有预定义角色,我们将在下面的部分中介绍。
经典菜单如下所示:
const { Menu } = require('electron')
const template = [
{
label: 'About us',
submenu: [
{
label: "About the app",
click() {
console.log("Hello world")
// TO DO
}
},
]
},
]
//在app监听到ready消息的响应中,创建窗口之后,loadFile之前加上:
var m = Menu.buildFromTemplate(template); //按照模板构建菜单
Menu.setApplicationMenu(m); //使菜单处于可用状态
每个菜单都有一个子菜单,我们在其中指示菜单项,这些菜单项可以是我们稍后看到的自定义或预定义角色;我们将:
根据操作系统的不同,它将有一种或另一种设计(,因为菜单的使用是您所在操作系统的固有功能,因此,从Windows开始,我们将看到:
正如您在上面的代码中所看到的,每个菜单都由一个数组组成,就像子菜单由一个阵列组成一样,因此,我们可以使用以下选项自定义我们认为合适的选项:
菜单的主要思想是,我们可以包括在整个应用程序中使用的自定义选项;因此,它们被用作与按钮相关联的JavaScript点击事件(例如),但在这种情况下,它不是按钮,而是菜单中的一个选项:
index.js
const { app, BrowserWindow, Menu,shell } = require("electron");
const template = [
{
label: "About us",
submenu: [
{
label: "About the app",
click() {
shell.openExternal("https://www.electronjs.org")
},
},
],
},
];
使用shell,我们可以打开一个链接上的网页,就好像它是一个导航链接一样。
它的使用非常简单,当我们想要使用自定义方法时,它们就是我们使用的。
对于角色,我们已经有了可以轻松重用的特定功能:
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ role: 'togglefullscreen' }
我们还有分隔符来组织菜单:
{
type:'separator'
},
举例如下:
template = [
{
label: 'MacOS',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{
type: 'separator'
},
{ role: 'togglefullscreen' },
]
}
]
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu)
有了这个,我们可以在应用程序中创建自定义菜单;我们可以利用菜单通过之前展示的事件和消息传递流程的使用,但我们将在下面的章节中展示这一点。
globalShortcut模块可以在操作系统中注册(或覆盖)全局键盘快捷键,以便您可以自定义各种快捷键的操作,以在每种情况下执行特定功能;例如,著名的Control/Command+S组合保存应用程序状态,很容易在Electron.js中捕获:
const { globalShortcut } = require('electron')
globalShortcut.register('CommandOrControl+S', () => {
// TO DO
});
要取消或取消注册一个组合:
globalShortcut.unregister('CommandOrControl+X')
要覆盖或取消注册所有快捷方式:
globalShortcut.unregisterAll()
从菜单中,我们还可以指定加速器(accelerator)属性来指定键盘快捷键:
const { Menu, shell } = require('electron')
const template = [
{
label: 'File',
submenu: [
{
label: "Save",
accelerator: 'CommandOrControl+S',
click() {
// TO Do
}
}
]
},
]
Windows是Electron.js的中心点之一,能够使用或创建允许应用程序中其他功能的其他窗口,如登录、注册等,是一个非常有用的功能,在当今任何应用程序中都是必要的;在本节中,我们将了解如何在Electron.js中使用windows。
要获得窗口的id,我们有id属性:
<window>.id
通过它,我们可以在窗口上执行其他类型的操作,例如引用一个现有的窗口或关闭它,我们将在下面的部分中看到。
要创建其他窗口,请使用“BrowserWindow()”对象的实例,遵循与主窗口相同的模式。例如,我们可以将主进程中的一个事件关联起来,该事件在激活时会创建一个额外的窗口:
ipcMain.on('open-window',(event,data)=>{
let newWin = new BrowserWindow({
width: 800,
height:600,
// webPreferences:{
// nodeIntegration: true,
// contextIsolation: false
// }
})
newWin.loadURL('https://www.google.com/')
//newWin.loadFile("index.html")
})
从网页上,我们向主流程中定义的事件发送消息以打开窗口;需要注意的是,您可以根据需要多次发送“打开窗口”事件来创建窗口,并且将创建具有不同id的独立窗口,因此,这一点的潜力是无限的,根据您的需求,您可以为网站显示不同的内容:
ipcRenderer.send('open-window')
在Electron.js中,我们有很多函数和属性可以用于windows;由于“BrowserWindow()”模块,我们可以使用所有这些函数,其中包括:
试着关闭这个窗口。这与用户手动单击窗口的关闭按钮相同。但是,该网页可以取消关闭:
<window>.close()