将Angular 7与ElectronJS结合起来
ElectronJS是一个开源框架,用于使用HTML、CSS和JavaScript等网络技术构建跨平台的本地桌面应用程序,能够在Windows、macOS和Linux操作系统上运行。它将Chromium引擎和NodeJS结合到一个单一的运行时间。
Electron可以与几个强大的框架相结合,如Angular 4+、AngularJS 1.x、React等,用于构建复杂的应用程序并提供增强的功能。Electron的核心是一个NodeJS应用程序,它可以与本地操作系统环境互动。通过NodeJS的集成,我们可以访问一些低级别的API,否则在沙盒浏览器环境下是无法访问的。通过Angular集成,我们可以获得一些优势和功能,如MVC(模型-视图-控制器)架构、模块和自定义指令。本教程将演示如何将Angular 7与ElectronJS集成,并从Angular中访问Electron的API。
我们假定你已经熟悉了上述链接中所涉及的先决条件。为了让Electron和Angular工作,需要在系统中预先安装node和npm。
注意:本教程也适用于Angular 5以上版本的工作。
例子:按照给定的步骤,将Angular 7与Electron集成。
- 第1步:导航到一个空目录来设置项目,并运行以下命令。
npm install -g @angular/cli
要在全球范围内安装Angular CLI。Angular CLI工具用于创建项目,执行测试和部署等任务,并生成代码的各种组件。通过运行以下命令创建一个新的Angular项目,并提供你选择的项目名称。
ng new ang-electron
这个命令提示你提供要包括在项目中的特征信息。按回车键选择合适的。
这也将把所需的Angular依赖和包安装到node_modules中。一旦完成,使用npm安装Electron并将其保存为dev-dependency。
npm install electron --save-dev
在这一点上,Angular应用程序已经准备好了,可以在本地提供服务。要在本地主机上提供应用程序,请运行以下命令。
cd ang-electron
ng serve
- 第二步:我们将通过代码连接这两个框架来启动Electron应用程序,并使其使用Angular。与任何Electron项目一样,我们需要创建一个进入应用程序的入口点。在我们的基本项目文件夹中创建main.js文件。这个文件将是我们进入应用程序的入口。
main.js:
const { app, BrowserWindow } = require('electron')
function createWindow () {
// Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// Load the index.html of the app
// From the dist folder which is created
// After running the build command
win.loadFile('dist/ang-electron/index.html')
// Open the DevTools.
win.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
// This method is equivalent to 'app.on('ready', function())'
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their
// menu bar to stay active until the user quits
// explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the
// app when the dock icon is clicked and there are
// no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
// In this file, you can include the rest of your app's
// specific main process code. You can also put them in
// separate files and require them here.
关于main.js文件的模板代码,请参考这个链接。我们已经根据我们的项目需要修改了代码。一旦我们运行构建命令,它将在dist文件夹中创建我们的angular项目的分布。我们将从这个文件夹中引用index.html文件。
- 第3步:需要对位于src文件夹中的index.html文件做一个小的改动。替换以下代码。
<base href="/">
with
<'base href="./">
这一改动很重要,否则它将无法找到并引用从dist文件夹中运行应用程序所需的必要文件。我们还需要对package.json文件做一些修改。
package.json:
{
"name": "ang-electron",
"version": "0.0.0",
"main": "main.js",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"electron": "ng build && electron ."
},
// ...
我们已经按照Electron的要求指定了main.js文件。我们还在scripts标签中引入了一个新的自定义electron命令来构建和启动应用程序。ng build命令用于构建Angular应用程序和部署构建工件。它将生成的构建工件写到输出文件夹中。默认情况下,输出文件夹是dist/ .
输出:一旦完成了相应的修改,我们就可以启动Electron应用程序了。要启动该应用程序,请运行以下命令。
npm run electron
- 第四步:到此为止,我们已经成功地将Angular与Electron整合在一起。要在Angular中使用Electron的API,我们可以遵循以下两种方法中的任何一种。
- 方法一:使用外部包来访问Electron的API。我们将使用ngx-electron npm包来实现这一目的。我们可以使用这个包作为一个简单的Angular服务来访问Electron APIs。更详细的信息,请参考这个链接。要安装这个包,运行以下命令。
npm install ngx-electron --save
一旦它被成功安装,我们将在我们的app.module.ts文件中导入它,以便在整个应用程序中使用它。
app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { NgxElectronModule } from 'ngx-electron';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
NgxElectronModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
关于这个包所支持的Electron API的列表,请参考这个https://www.npmjs.com/package/ngx-electron#properties 。我们将使用ngx-electron包中的Electron shell API。
app.component.html:
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
<button (click)="openWindow()">
Click here to Access GeeksForGeeks
</button>
<router-outlet></router-outlet>
点击这里访问GeeksForGeeks按钮没有任何相关的功能。要改变这一点,请对app.component.ts文件做如下修改。
app.component.ts:
import { Component } from '@angular/core';
import { ElectronService } from 'ngx-electron';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ang-electron';
constructor(private electronService: ElectronService) {}
openWindow() {
// Accessing the Shell API from ngx-electron
this.electronService
.shell.openExternal('https://www.geeksforgeeks.org/');
}
}
ElectronService暴露了所有可以从渲染器进程中访问的Electron API。我们将通过依赖性注入在构造函数中创建一个ElectronService的实例。
输出:
- 方法2:通过创建一个Electron服务组件,并在整个应用程序中共享它以使用Electron APIs。我们将通过运行以下CLI命令来生成Electron服务。
ng generate service elec --skipTests=true
-skipTests=true不会为新服务创建spec.ts测试文件。这个命令将在src/app文件夹下生成一个新的elec.service.ts文件。在这个文件中,我们将声明并添加所有的Electron Imports,然后可以在整个应用程序中使用。我们将使用主进程中的Electron shell API。
elec.service.ts:
import { Injectable } from '@angular/core';
import { shell } from 'electron';
@Injectable({
providedIn: 'root'
})
export class ElecService {
shell: typeof shell;
constructor() {
this.shell = (<any>window).require("electron").shell;
}
}
any关键字是用于窗口对象的类型断言。使用any转换这个对象表明你不再被编译器约束到窗口对象的默认属性。这被用来防止在使用Electron模块时出现编译时类型错误。如果在windows对象上忽略了类型转换,我们将收到以下错误。
ERROR in ./node_modules/electron/index.js
Module not found: Error: Can't resolve 'fs'
typeof运算符以字符串的形式返回其操作数的数据类型。在这个例子中,操作数是Electron的外壳模块。使用这种方法可以让我们在整个应用程序中访问所有的Electron APIs。为了使用这个服务,在app.component.ts文件中添加以下内容。
app.component.ts:
import { Component } from '@angular/core';
import { ElectronService } from 'ngx-electron';
import { ElecService } from '../app/elec.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ang-electron';
// Creating Instances through Dependency Injection
constructor(private electronService: ElectronService,
private elecService: ElecService) {}
openWindow() {
// Accessing the Shell API from ngx-electron
// this.electronService
// .shell.openExternal('https://www.geeksforgeeks.org/');
// Accessing the Shell API from ElecService
this.elecService.shell
.openExternal('https://www.geeksforgeeks.org/');
}
}
输出: