angular quick start tutorial summary

Angular Home

angular.cn
angular.io
angular-in-memory-web-api

Creat

你使用 CLI 创建了第二个组件 HeroesComponent。
ng generate component heroes
你把 HeroesComponent 添加到了壳组件 AppComponent 中,以便显示它。
app.component.html <app-heros></app-heros>
你使用 UppercasePipe 来格式化英雄的名字。
heros.component.html <h2>{{hero.name | uppercase}} Details</h2>
你用 ngModel 指令实现了双向数据绑定。
<input [(ngModel)]="hero.name" placeholder="name">
你知道了 AppModule。
添加元数据的地方,Angular 需要知道如何把应用程序的各个部分组合到一起,以及该应用需要哪些其它文件和库。 这些信息被称为元数据(metadata)
你把 FormsModule 导入了 AppModule,以便 Angular 能识别并应用 ngModel 指令。
app.module.ts import { FormsModule } from '@angular/forms'; // <-- NgModel lives here imports: [ BrowserModule, FormsModule ],
你知道了把组件声明到 AppModule 是很重要的,并认识到 CLI 会自动帮你声明它。
@NgModule({ declarations: [AppComponent,HerosComponent],。。。})

Display

英雄指南应用在一个主从视图中显示了英雄列表。
click事件 html <li *ngFor="let hero of heroes" (click)="onSelect(hero)"> ts onSelect(hero: Hero): void {this.selectedHero = hero;}
用户可以选择一个英雄,并查看该英雄的详情。
<input [(ngModel)]="selectedHero.name" placeholder="name">
你使用 *ngFor 显示了一个列表。
<li *ngFor="let hero of heroes" [class.selected]='hero === selectHero' (click)="onSelect(hero)">
你使用 *ngIf 来根据条件包含或排除了一段 HTML。
<div *ngIf='selectHero'></div>
你可以用 class 绑定来切换 CSS 的样式类。
[class.selected]='hero === selectHero'

Master/Detail

你创建了一个独立的、可复用的 HeroDetailComponent 组件。
ng generate component hero-detail
你用属性绑定语法来让父组件 HeroesComponent 可以控制子组件 HeroDetailComponent。 import { Hero } from '../hero'; @Input() hero: Hero;
你用 @Input 装饰器来让 hero 属性可以在外部的 HeroesComponent 中绑定
<app-hero-detail [hero]="selectedHero"></app-hero-detail> import { Input } from '@angular/core';

Service

你把数据访问逻辑重构到了 HeroService 类中。
组件不应该直接获取或保存数据, 它们应该聚焦于展示数据,而把数据访问的职责委托给某个服务
你在根模块 AppModule 中提供了 HeroService 服务,以便在别处可以注入它。
ng generate service hero --module=app //not insert automatically import { HeroService } from './hero.service'; @NgModule({providers: [HeroService]})
你使用 Angular 依赖注入机制把它注入到了组件中。
heroes.component.ts: import { HeroService } from '../hero.service'; constructor(private heroService: HeroService) { }
你给 HeroService 中获取数据的方法提供了一个异步的函数签名。
服务是在多个“互相不知道”的类之间共享信息的好办法
回调函数,可以返回 Promise(承诺),也可以返回 Observable(可观察对象)
你发现了 Observable 以及 RxJS 库。
import { Observable, of } from 'rxjs';
你使用 RxJS 的 of() 方法返回了一个模拟英雄数据的可观察对象 (Observable<Hero[]>)。 getHeroes(): Observable<Hero[]> { this.messageService.add('HeroService: fetched heroes'); return of(HEROES); }
在组件的 ngOnInit 生命周期钩子中调用 HeroService 方法,而不是构造函数中。
让构造函数保持简单,只做初始化操作,比如把构造函数的参数赋值给属性。 构造函数不应该做任何事
你创建了一个 MessageService,以便在类之间实现松耦合通讯。
ng generate service message --module=app
HeroService 连同注入到它的服务 MessageService 一起,注入到了组件中。
hero.service.ts: import { MessageService } from './message.service'; constructor(private messageService: MessageService) { } export class HeroesComponent implements OnInit { constructor(private heroService: HeroService) {} ngOnInit() {this.getHeroes();} getHeroes(): void {this.heroService.getHeroes().subscribe(heroes => this.heroes = heroes);} }

Router

添加了 Angular 路由器在各个不同组件之间导航。
ng generate module app-routing --flat --module=app
你使用一些 <a>链接和一个<router-outlet> 把 AppComponent 转换成了一个导航用的壳组件。
`app.component.html

` 你在 AppRoutingModule 中配置了路由器。 ` const routes: Routes = [ { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'heroes', component: HeroesComponent }, { path: 'dashboard', component: DashboardComponent }, { path: 'detail/:id', component: HeroDetailComponent }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)]... })` 你定义了一些简单路由、一个重定向路由和一个参数化路由。 `{ path: 'heroes', component: HeroesComponent }, { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'detail/:id', component: HeroDetailComponent },` 你在 ` ` 元素中使用了 routerLink 指令。 `dashboard.component.html&heroes.component.html ` 你把一个紧耦合的主从视图重构成了带路由的详情视图。 `hero-detail.component.ts export class HeroDetailComponent implements OnInit { @Input() hero: Hero; constructor( private route: ActivatedRoute, private heroService: HeroService, private location: Location) { } ngOnInit() { this.getHero(); } getHero(): void { const id = +this.route.snapshot.paramMap.get('id'); this.heroService.getHero(id) .subscribe(hero => this.hero = hero); } }` 你使用路由链接参数来导航到所选英雄的详情视图。 `getHero(): void { const id = +this.route.snapshot.paramMap.get('id'); this.heroService.getHero(id) .subscribe(hero => this.hero = hero); }` 在多个组件之间共享了 HeroService 服务。 ` hero.service.ts//读取数据的服务 use: dashboard.component.ts&heroes.component.ts&hero-detail.component.ts`

HTTP

你添加了在应用程序中使用 HTTP 的必备依赖。
hero.service.ts import { HttpClient, HttpHeaders } from '@angular/common/http'; constructor( private http: HttpClient, private messageService: MessageService) { }

你重构了 HeroService,以通过 web API 来加载英雄数据。

  return this.http.get<Hero[]>(this.heroesUrl) //return of(HEROES);
    .pipe(
      tap(heroes => this.log(`fetch heroes`)),
      catchError(this.handleError('getHeroes', [])
      ));
}```
你扩展了 HeroService 来支持 post()、put() 和 delete() 方法。
```hero.service.ts 
  updateHero(hero: Hero): Observable<any> {
    return this.http.put(this.heroesUrl, hero, httpOptions).pipe(
      tap(() => this.log(`update hero id = ${hero.id}`)),
      catchError(this.handleError<any>('updateHero'))
    );
  }
  addHero(hero: Hero): Observable<Hero> {
    return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
      tap(() => this.log(`add hero w/ id=${hero.id}`)),
      catchError(this.handleError<Hero>('addHero'))
    );
  }
  deleteHero(hero: Hero | number): Observable<Hero> {
    const id = typeof hero === 'number' ? hero : hero.id;
    const url = `${this.heroesUrl}/${id}`;
    return this.http.delete<Hero>(url, httpOptions).pipe(
      tap(() => this.log(`delete hero id=${id}`)),
      catchError(this.handleError<Hero>('deleteHero'))
    );
  }```

你修改了组件,以允许用户添加、编辑和删除英雄。
`heroes.component.html
  <label>Hero Name:
    <input #heroName> 
  </label>
  <button (click)="add(heroName.value);heroName.value=''">add</button>
heroes.component.ts 
  add(name:string):void{
    name=name.trim();
    if(!name) return;
    this.heroService.addHero({name} as Hero)
    .subscribe(hero=>{this.heroes.push(hero);});
  }`

你配置了一个内存 Web API。
`npm install angular-in-memory-web-api --save
app.module.ts
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService }  from './in-memory-data.service';
in-memory-data.service.ts
import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
  construct (){}
  createDb() {
    const heroes = [
      { id: 11, name: 'Mr. Nice' } ];
    return {heroes};
  }
}`
你学会了如何使用“可观察对象”。
  `通常,Observable 可以在一段时间内返回多个值。 
  但来自 HttpClient 的 Observable 总是发出一个值,然后结束,再也不会发出其它值。
  使用 RxJS 的 catchError() 操作符来建立对 Observable 结果的处理管道(pipe)
  import { catchError, map, tap } from 'rxjs/operators';
  现在,使用 .pipe() 方法来扩展 Observable 的结果,并给它一个 catchError() 操作符。
  getHeroes (): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
        catchError(this.handleError('getHeroes', []))
      );
  }`
  使用 RxJS的tap查看Observable中的值,使用那些值做一些事情,并且把它们传出来.这种tap回调不会改变这些值本身
  ```/** GET heroes from the server */
  getHeroes (): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
        tap(heroes => this.log(`fetched heroes`)),
        catchError(this.handleError('getHeroes', []))
      );
  }

基本概念

架构概览
Angular 是一个用 HTML 和 TypeScript 构建客户端应用的平台与框架。 Angular 本身使用 TypeScript 写成的。它将核心功能和可选功能作为一组 TypeScript 库进行实现,你可以把它们导入你的应用中。
Angular 的基本构造块是 NgModule,它为组件提供了编译的上下文环境。 NgModule 会把相关的代码收集到一些功能集中。Angular 应用就是由一组 NgModule 定义出的。 应用至少会有一个用于引导应用的根模块,通常还会有很多特性模块。

	组件定义视图。视图是一组可见的屏幕元素,Angular 可以根据你的程序逻辑和数据来选择和修改它们。 每个应用都至少有一个根组件。
	组件使用服务。服务会提供那些与视图不直接相关的功能。服务提供商可以作为依赖被注入到组件中, 这能让你的代码更加模块化、可复用,而且高效。
	组件和服务都是简单的类,这些类使用装饰器来标出它们的类型,并提供元数据以告知 Angular 该如何使用它们。
	组件类的元数据将组件类和一个用来定义视图的模板关联起来。 模板把普通的 HTML 和指令与绑定标记(markup)组合起来,这样 Angular 就可以在呈现 HTML 之前先修改这些 HTML。

服务的元数据提供了一些信息,Angular 要用这些信息来让组件可以通过依赖注入(DI)使用该服务。
应用的组件通常会定义很多视图,并进行分级组织。 Angular 提供了 Router 服务来帮助你定义视图之间的导航路径。 路由器提供了先进的浏览器内导航功能。

模块

Angular 定义了 NgModule,它和 JavaScript(ES2015) 的模块不同而且有一定的互补性。 NgModule 为一个组件集声明了编译的上下文环境,它专注于某个应用领域、某个工作流或一组紧密相关的能力。 NgModule 可以将其组件和一组相关代码(如服务)关联起来,形成功能单元。
每个 Angular 应用都有一个根模块,通常命名为 AppModule。根模块提供了用来启动应用的引导机制。 一个应用通常会包含很多功能模块。
像 JavaScript 模块一样,NgModule 也可以从其它 NgModule 中导入功能,并允许导出它们自己的功能供其它 NgModule 使用。 比如,要在你的应用中使用路由器(Router)服务,就要导入 Router 这个 NgModule。
把你的代码组织成一些清晰的功能模块,可以帮助管理复杂应用的开发工作并实现可复用性设计。 另外,这项技术还能让你获得惰性加载(也就是按需加载模块)的优点,以尽可能减小启动时需要加载的代码体积。
更深入的讨论,参见模块简介。

组件

每个 Angular 应用都至少有一个组件,也就是根组件,它会把组件树和页面中的 DOM 连接起来。 每个组件都会定义一个类,其中包含应用的数据和逻辑,并与一个 HTML 模板相关联,该模板定义了一个供目标环境下显示的视图。
@Component 装饰器表明紧随它的那个类是一个组件,并提供模板和该组件专属的元数据。
装饰器是一些用于修饰 JavaScript 类的函数。Angular 定义了许多装饰器,这些装饰器会把一些特定种类的元数据附加到类上,以便 Angular 了解这些这些类的含义以及该如何使用它们。
到网上学习关于装饰器的更多知识。

模板、指令和数据绑定

模板会把 HTML 和 Angular 的标记(markup)组合起来,这些标记可以在 HTML 元素显示出来之前修改它们。 模板中的指令会提供程序逻辑,而绑定标记会把你应用中的数据和 DOM 连接在一起。
事件绑定让你的应用可以通过更新应用的数据来响应目标环境下的用户输入。
属性绑定让你将从应用数据中计算出来的值插入到 HTML 中。
在视图显示出来之前,Angular 会先根据你的应用数据和逻辑来运行模板中的指令并解析绑定表达式,以修改 HTML 元素和 DOM。 Angular 支持双向数据绑定,这意味着 DOM 中发生的变化(比如用户的选择)同样可以反映回你的程序数据中。
你的模板也可以用管道转换要显示的值以增强用户体验。比如,可以使用管道来显示适合用户所在地区的日期和货币格式。 Angular 为一些通用的转换提供了预定义管道,你还可以定义自己的管道。
要了解对这些概念的深入讨论,参见组件介绍。

服务与依赖注入

对于与特定视图无关并希望跨组件共享的数据或逻辑,可以创建服务类。 服务类的定义通常紧跟在 “@Injectable” 装饰器之后。该装饰器提供的元数据可以让你的服务作为依赖被注入到客户组件中。
依赖注入(或 DI)让你可以保持组件类的精简和高效。有了 DI,组件就不用从服务器获取数据、验证用户输入或直接把日志写到控制台,而是会把这些任务委托给服务。
更深入的讨论,参见服务和 DI 简介。

路由

Angular 的 Router 模块提供了一个服务,它可以让你定义在应用的各个不同状态和视图层次结构之间导航时要使用的路径。 它的工作模型基于人们熟知的浏览器导航约定:
在地址栏输入 URL,浏览器就会导航到相应的页面。
在页面中点击链接,浏览器就会导航到一个新页面。
点击浏览器的前进和后退按钮,浏览器就会在你的浏览历史中向前或向后导航。
不过路由器会把类似 URL 的路径映射到视图而不是页面。 当用户执行一个动作时(比如点击链接),本应该在浏览器中加载一个新页面,但是路由器拦截了浏览器的这个行为,并显示或隐藏一个视图层次结构。
如果路由器认为当前的应用状态需要某些特定的功能,而定义此功能的模块尚未加载,路由器就会按需惰性加载此模块。
路由器会根据你应用中的导航规则和数据状态来拦截 URL。 当用户点击按钮、选择下拉框或收到其它任何来源的输入时,你可以导航到一个新视图。 路由器会在浏览器的历史日志中记录这个动作,所以前进和后退按钮也能正常工作。
要定义导航规则,你就要把导航路径和你的组件关联起来。 路径(path)使用类似 URL 的语法来和程序数据整合在一起,就像模板语法会把你的视图和程序数据整合起来一样。 然后你就可以用程序逻辑来决定要显示或隐藏哪些视图,以根据你制定的访问规则对用户的输入做出响应。
更深入的讨论,参见路由与导航。
接下来呢?
What’s next
你已经学完了 Angular 应用的主要构造块的基础知识。 下面这张图展示了这些基础部分之间是如何关联起来的。
在这里插入图片描述
overview
组件和模板共同定义了 Angular 的视图。
组件类上的装饰器为其添加了元数据,其中包括指向相关模板的指针。
组件模板中的指令和绑定标记会根据程序数据和程序逻辑修改这些视图。
依赖注入器会为组件提供一些服务,比如路由器服务就能让你定义如何在视图之间导航。

猜你喜欢

转载自blog.csdn.net/sgs595595/article/details/80443510
今日推荐