Angular教程

时间:2020-02-23 14:29:32  来源:igfitidea点击:

Angular是一个客户端JavaScript框架,专门用于帮助开发人员根据Web开发的最佳实践来构建SPA(单页应用程序)。
通过提供用于构建SPA的结构化环境,可以大大降低产生"意大利面条代码"的风险。
因此,我们一定想知道什么是SPA?

单页应用程序(或者SPA的)是可以通过Web浏览器(如其他)访问的应用程序,但提供了更多类似于本地移动和桌面应用程序的动态交互。
常规和SPA之间最显着的区别是页面刷新量减少。
SPA大量使用AJAXa方式与后端服务器进行通信,而无需执行整页刷新即可将数据加载到我们的应用程序中。
结果,呈现页面的过程主要发生在客户端。

例如,如果我们浏览Gmail,我们会注意到从收件箱打开邮件时只会提取电子邮件并在电子邮件列表中显示它。
侧列,导航列等其余组件不会重新加载。
它仅刷新所需部分的DOM(文档对象模型)。
因此,这减少了的负担。

因此,现在我们知道什么是Javascript&Jquery以及如何引入Angular。
在Angular 8教程中继续前进,我们将浏览一下angular的函数并了解如何使用Angular。

Angular 8教程

Angular是一个基于TypeScript的开源前端Web应用程序平台,由Google的Angular团队以及个人和社区组成。
Angular是构建AngularJS的同一团队的完整重写。
但让我告诉我们Angular与AngularJS完全不同。
让我们了解Angular和AngularJS之间的区别。

Angular和AngularJS之间的区别

  • Angular应用程序的体系结构与AngularJS不同。 Angular的主要构建模块是模块,组件,模板,元数据,数据绑定,指令,服务和依赖项注入。我们将在一段时间内进行研究。

  • Angular没有"作用域"或者控制器的概念,它使用组件的层次结构作为其主要架构概念。

  • Angular具有更简单的表达式语法,专注于" []"进行属性绑定,而关注"()"进行事件绑定

  • 移动开发–如果首先处理移动性能问题,则桌面开发会容易得多。因此,Angular首先处理移动开发。

  • 模块化– Angular遵循模块化。相似的函数放在同一模块中。这使Angular的内核更轻,更快。

Angular建议使用Microsoft的TypeScript语言,该语言引入了以下函数:

  • 基于类的面向对象程序设计

  • 静态打字

TypeScript是ECMAScript 6(ES6)的超集,并与ECMAScript 5向后兼容。
Angular 8还包括ES5到ES2014 +的优点:

  • 迭代器

  • For/Of循环

  • 反射

  • 改进的依赖项注入–绑定使命名关系成为可能

  • 动态加载

  • 异步模板编译

  • 更简单的路由

  • 用组件和指令替换控制器和$scope –组件是带有模板的指令

  • 支持使用RxJS进行反应式编程

继续本Angular 8教程,让我们了解Angular的函数。

Angular特征

跨平台

渐进式Web应用程序:它使用现代Web平台函数来提供类似应用程序的体验。
它提供了高性能,离线和零步骤安装。
因此,使用Angular非常容易。

本机:我们可以使用Ionic Framework,NativeScript和React Native的策略来构建本机移动应用程序。

台式机:使用我们在网上学习的相同Angular方法,跨Mac,Windows和Linux创建在台式机上安装的应用。

速度与性能

代码生成:Angular将模板转换为针对JavaScript虚拟机进行高度优化的代码,为我们提供手写代码的所有优势以及框架的生产力。

通用:可以将Angular的任何技术用于为该应用程序提供服务,例如node.js,.NET,PHP和其他服务器

代码拆分:Angular应用程序通过新的Component Router快速加载,该路由器提供自动代码拆分函数,因此用户仅加载呈现其请求视图所需的代码。

生产率

模板:使用简单而强大的模板语法快速创建UI视图。

Angular CLI:命令行工具:我们可以轻松,快速地开始构建组件,添加组件,测试它们,然后使用Angular CLI即时部署它们。

IDE:在流行的编辑器和IDE(如Microsoft的VS Code)中获得智能的代码完成,即时错误和其他反馈。

完整的发展故事

测试:使用Jasmine测试框架,Angular CLI会下载并安装测试应用程序所需的一切。
当我们运行ng test命令时,该应用将以 watch 模式构建,并且将启动Karma测试运行程序。
完成后,我们将在终端中看到输出,加上chrome浏览器将打开,并在Jasmine HTML Reporter中显示输出。

Angular 8的新函数:

TypeScript 3.4:Angular 8需要使用TypeScript 3.4进行Web开发

Opt-n Ivy Preview:Ivy是Angular的下一代编译和渲染管道的名称。
这将有选择地预览以查看其运作方式

差异加载:作为其构建过程的一部分,Angular 8 CLI将能够生成旧版和现代JS捆绑包,例如:ES5和ES2014 +。
这意味着对于当前的浏览器来说,差异化的客户端具有改进的速度和TTI(交互时间)

路由器的向后兼容性:这有助于简化大型项目的升级路径

参与使用共享:使用此函数,Angular团队将能够在我们同意的情况下收集匿名信息,以跟踪所使用的命令以及构建项目所花费的时间

依赖关系更新:Angular 8更新了对工具的依赖,例如RxJS,Node和TypeScript(如前所述),以提高性能并与当前环境同步

Web Worker构建:Web Worker允许我们编写与主线程分开运行的代码。
通过并行执行多个任务可以提高速度。
由于开发人员的要求,Angular 8的开发人员增加了对Web Worker的捆绑支持

Angular的构建基块

Angular的主要构建块是:

  • 模组

  • 成分

  • 范本

  • 元数据

  • 数据绑定

  • 指令

  • 服务

  • 依赖注入

图:Angular 8教程–体系结构

模组

Angular应用程序是模块化的,并且为了保持模块化,我们有Angular模块,或者我们可以说NgModules。
每个Angular应用程序至少包含一个Angular模块,例如:根模块。
通常,它被命名为AppModule。
在小型应用程序中,根模块可以是唯一的模块。
虽然大多数应用程序具有多个模块。
我们可以说,模块是具有相关函数集的内聚代码块,这些函数集具有特定的应用程序域或者工作流。
任何Angular模块都是带有@NgModule装饰器的类。

装饰器是用于修改JavaScript类的函数。
装饰器基本上用于将元数据添加到类,以便它知道那些类的配置以及它们应如何工作。
NgModule是一个装饰器函数,该函数接受元数据对象,其属性描述模块。
这些属性是:

  • 声明:与视图相关的类,它们属于此模块。 Angular有三类可以包含视图:组件,指令和管道。我们将在一段时间内谈论它们。

  • 出口:其他模块的组件应可访问的类。

  • imports:此模块的组件需要其类的模块。

  • 提供者:在一个模块中存在的服务,这些模块将在其他模块或者组件中使用。一旦服务包含在提供程序中,它就可以在该应用程序的所有部分中访问

  • bootstrap:根组件,它是应用程序的主视图。该根模块仅具有此属性,它指示要引导的组件。

让我们看一下根模块(即src/app/app.module.ts)最初的样子:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

根模块通常不会导出其类,因为根模块是导入其他模块和组件以使用它们的根模块。
我们将AppModule引导到main.ts文件中,其中指定引导模块,在引导模块内部,它包含引导组件。

import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
  enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
  .catch(err => console.error(err));

Angular库

Angular为我们提供了提供各种函数JavaScript模块(库模块)的集合。
每个Angular库都有@angular前缀,例如@ angular/core,@ angular/compiler,@ angular/compiler-cli,@ angular/http,@ angular/router。
我们可以使用npm软件包管理器进行安装,并使用JavaScript import语句导入其中的一部分。

import { Component } from '@angular/core';

在上面的示例中,Angular的Component装饰器是从@ angular/core库导入的。

现在,在Angular 8教程中继续前进,让我们了解Angular的下一个和重要的构建基块,例如:组件。

成分

组件控制屏幕上称为视图的一个或者多个部分。
例如,如果要构建类列表应用程序,则可以具有诸如App Component(自举组件),Course Component,Course Detail Component等组件。

在组件内部,我们可以定义一个组件的应用程序逻辑,例如:在类内部,它如何支持视图。
该类通过属性和方法的API与视图进行交互。

每个应用程序都有一个在主模块内部引导的主要组件,例如:AppComponent。

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'theitroad!';
}

因此,在查看了自举组件之后。
现在让我们看一下另一个组件,例如:类组件,使我们对组件有了更好的了解。

import { Component, OnInit } from '@angular/core';
import { Course } from '../courses';
import { CoursesService } from '../courses.service';
@Component({
  selector: 'app-course',
  templateUrl: './course.component.html',
  styleUrls: ['./course.component.css']
})
export class CourseComponent implements OnInit {
  courses: Course[];
 
  constructor(private courseService: CoursesService) { }
  ngOnInit() {
    this.getCourses();
  }
  
  getCourses(): void {
    this.courseService.getCourses().subscribe(course => this.courses = course);
  }
}

其中我们首先使用import关键字导入我们在组件中所需的组件和依赖项。
然后,我们使用@Component装饰器添加组件的元数据。
第一个属性是选择器,它以关键字为目标并在所选标记内转储数据。
我们可以使用两种方法添加视图:可以添加模板属性并在此处指定模板,也可以使用templateUrl并提供包含模板的文件的路径。
稍后我们将详细讨论模板。
第三个属性是styleUrls,它提供CSS样式表的路径。
(有关完整的代码,请参阅本文开头提供的视频)

然后,在元数据之后,我们指定位于类内部的组件的逻辑。
我们指定了构造函数,并其中指定了变量和方法,这些变量和方法在创建类时需要初始化。
然后,我们还有ngOnInit方法,该方法在实例化组件时被调用。

移至Angular 8教程中的下一个构建块,例如:模板。

范本

我们将组件的视图与其伴侣模板相关联。
模板不过是HTML标记的一种形式,它告诉Angular如何呈现组件。
模板看起来像普通HTML,但有一些区别。
这是如上所述的CourseComponent的模板:

<h2>All Courses</h2>

<ul class="course">

<li *ngFor="let course of courses">
      <a routerLink="/detail/{{course.id}}"></a>
    <span class="badge">{{course.id}} {{course.name}}
</ul>

元数据

元数据告诉Angular如何处理一个类。
为了告诉Angular类组件是一个组件,将元数据添加到该类。
在TypeScript中,我们可以使用decorator添加元数据。
在以下代码中,我们可以看到类组件附带的元数据:

@Component({
  selector: 'app-course',
  templateUrl: './course.component.html',
  styleUrls: ['./course.component.css']
})

这是@Component装饰器,它将紧靠其下的类标识为组件类。
@Component装饰器采用Angular创建和呈现组件及其视图所需的配置对象。

@Component装饰器的最重要的配置是:

  • 选择器:选择器告诉Angular在找到<app-course>标签的位置创建并插入此组件的实例。例如,如果应用HTML包含<app-course> </app-course>,则Angular将在这些标签之间插入CourseComponent视图的实例。

  • templateUrl:它包含此组件HTML模板的路径。

  • styleUrls:这是特定于组件的样式表。

@Component中的元数据告诉Angular其中获取为该组件指定的主要构建块。
模板,元数据和组件一起描述了一个视图。
架构上的要点是必须将元数据添加到代码中,以便Angular知道该怎么做。

数据绑定

如果不使用框架,则必须将数据值推送到HTML控件中,并将用户响应转换为某些操作和值更新。
编写这样的推/拉逻辑很繁琐,容易出错,并且是一场噩梦。
Angular支持数据绑定,这是一种用于将模板的各个部分与组件的各个部分进行协调的机制。
我们应该在模板HTML中添加绑定标记,以告诉Angular如何连接双方。

图:Angular 8教程–数据绑定

每种形式都有一个方向-从DOM到DOM,或者在两个方向上。

<li> {{course.name}}</li>

<course-detail [course]="selectedCourse"></course-detail>

<li (click)="selectCourse(Course)"></li>
  • {{course.name}}插值在<li>元素内显示组件的name属性值。

  • [course]属性绑定将selectedCourse的值从CourseComponent传递到子CourseDetailComponent的course属性。

  • 当用户单击类名称时,(单击)事件绑定将调用组件的selectCourse方法。

双向数据绑定是重要的部分,因为它使用ngModel指令以单个符号组合了属性和事件绑定。
这是CourseDetailComponent模板中的示例:

<input [(ngModel)]="courses.name" placeholder="name"

在双向绑定中,数据属性值与属性绑定一样从组件流到输入框。
与事件绑定一样,用户所做的更改也将流回到组件,将属性重置为最新值。
从应用程序组件树的根到所有子组件,每个JavaScript事件周期Angular都会处理所有数据绑定一次。

数据绑定在模板与其组件之间的通信中起着重要作用。
数据绑定对于父子组件之间的通信也很重要。

在本《 Angular 8教程》中,我们将进一步讨论下一个构建块,例如:指令。

指令

Angular模板是动态的。
当Angular渲染它们时,它将根据伪指令给出的指令对DOM进行转换。
指令是带有@Directive装饰器的类。
组件是带有模板的指令。
@Component装饰器实际上是具有面向模板函数的@Directive装饰器。

虽然从技术上讲组件是指令,但组件是如此独特且对Angular应用程序至关重要,因此本体系结构概述将组件与指令分开。

存在两种其他类型的指令:结构指令和属性指令。

伪指令往往像属性一样出现在元素标签中,有时按名称显示,但更经常作为赋值或者绑定的目标。

结构化指令通过添加,删除和替换DOM中的元素来更改布局。

此示例模板使用两个内置的结构指令:

<li *ngFor="let course of coursess"></li>

<course-detail *ngIf="selectedCourse"></course-detail>
    • ngFor告诉Angular在类中每门类检索一个<li>
    • ngIf仅在存在所选类时才包括CourseDetail组件。

属性指令可更改现有元素的外观或者行为。
在模板中,它们看起来像常规HTML属性。
实现双向数据绑定的ngModel指令是属性指令的示例。
ngModel通过设置现有元素的显示值属性并响应更改事件来修改其行为。

<input [(ngModel)]="courses.name" placeholder="name"

Angular还有其他一些指令,它们可以更改布局结构(例如ngSwitch)或者修改DOM元素和组件的各个方面(例如ngStyle和ngClass)。

我们也可以编写自己的指令,例如:自定义指令。

服务

服务是一个广泛的类别,涵盖了应用程序所需的任何值,函数或者函数。
服务通常是具有明确定义目的的类。
任何东西都可以成为服务。
示例包括:

  • 测井服务

  • 数据服务

  • 消息总线

  • 税收计算器

  • 应用程序配置

图:Angular 8教程–服务

Angular没有服务的定义。
没有服务基类,也没有注册服务的地方。
然而,服务是任何Angular应用程序的基础。
组件是服务的使用者。

这是服务类别的示例:

import { Injectable } from '@angular/core';
import {Course} from './courses';
import { Observable, of } from 'rxjs';
import {COURSES} from './mock-course';
import { MessageService } from './messages.service';
@Injectable({
  providedIn: 'root'
})
export class CoursesService {
  constructor(private messageService: MessageService) { }
  getCourses(): Observable<Course[]> {
    //TODO: send the message _after_ fetching the heroes
    this.messageService.add('CourseService: fetched courses');
    return of(COURSES);
  }
  getCourse(id: number): Observable<Course>
  {
    this.messageService.add(`CoursesService: fetched courses id=${id}`);
    return of (COURSES.find(courses => courses.id === id));
  }
}

服务无处不在。
组件类不会从服务器获取数据,验证用户输入或者直接登录到控制台。
他们将此类任务委托给服务。

组件的工作就是提供用户体验,仅此而已。
它在视图(由模板渲染)和应用程序逻辑之间进行中介。
一个好的组件展示了数据绑定的属性和方法。
Angular确实使我们可以轻松地将应用程序逻辑分解为服务,并通过依赖注入使这些服务可用于组件,从而遵循这些原则。

因此,现在让我们在Angular 8教程教程 中了解依赖注入。

依赖注入

依赖注入是一种为类的新实例提供所需的完全依赖关系的方法。
大多数依赖项是服务。
Angular使用依赖注入为新组件提供所需的服务。
Angular可以通过查看其构造函数参数的类型来判断组件需要哪些服务。

当Angular创建组件时,它首先向注入器询问组件所需的服务。

图:Angular 8教程依赖注入

注入程序维护它先前创建的服务实例的容器。
如果请求的服务实例不在容器中,则注入器将其创建一个并将其添加到容器中,然后再将服务返回到Angular。
解析并返回所有请求的服务后,Angular可以使用这些服务作为参数来调用组件的构造函数。
这是一个依赖项注入。

在下面的示例中,我们可以看到,我们正在使用注入器注册Firebase Service的提供程序。
提供者是可以创建或者返回服务的东西,通常是服务类本身。
我们可以在模块或者组件中注册提供程序。

通常,将提供程序添加到根模块,以使服务的同一实例在任何地方都可用,如下面的代码所示。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; //<-- NgModel lives here
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CourseComponent } from './course/course.component';
import { CourseDetailComponent } from './course-detail/course-detail.component';
import { MessagesComponent } from './messages/messages.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import { FooterComponent } from './footer/footer.component';
@NgModule({
  declarations: [
    AppComponent,
    CourseComponent,
    CourseDetailComponent,
    MessagesComponent,
    DashboardComponent,
    FooterComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    NgbModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

另外,我们可以在@Component装饰器的providers属性中在组件级别注册服务:

import { Component } from '@angular/core';
import { FirebaseService } from './services/firebase.service';
 
@Component({
selector:'app-root',
templateUrl:'./app.component.html',
styleUrls: ['./app.component.css'],
providers: [FirebaseService]
})
export class AppComponent {
title = 'app works!';
}

(注意:有关完整的代码,请参阅上面指定的视频)

在组件级别注册意味着我们将获得该组件的每个新实例的服务新实例。

关于依赖项注入的总结,我们可以说:

  • 依赖注入被连接到Angular框架中,并在各处使用。

  • 进样器是主要机构。

  • 注入器维护它创建的服务实例的容器。

  • 注入程序可以从提供程序创建新的服务实例。

  • 提供者是创建服务的秘诀。

  • 向提供者注册提供者。