整理Angular官方文档https://angular.cn/tutorial/

运行 CLI 命令 ng new新建一个工作区

 ng new angular-tour-of-heroes

选择npm包和其他依赖项(上下键选择,而不是傻等着!)

会创建下列工作区和初始项目的文件:

  • 新的工作区,其根目录名叫 angular-tour-of-heroes

  • 一个最初的骨架应用项目,同样叫做 angular-tour-of-heroes(位于 src 子目录下)。

  • 一个端到端测试项目(位于 e2e 子目录下)。

  • 相关的配置文件。

启动应用

ng serve --open
ng generate component heroes

页面就是应用的外壳。 这个外壳是被一个名叫 AppComponent 的 Angular 组件控制的组件是 Angular 应用中的基本构造块。 它们在屏幕上显示数据,监听用户输入,并且根据这些输入执行相应的动作。

 src/app 目录中AppComponent 壳的三个实现文件:

  1. app.component.ts— 组件的类代码,这是用 TypeScript 写的。src/app/app.component.ts

  2. app.component.html— 组件的模板,这是用 HTML 写的。src/app/app.component.html

  3. app.component.css— 组件的私有 CSS 样式。  src/styles.css

创建一个名为 heroes 的新组件 (根目录下)

ng generate component heroes

CLI 创建了一个新的文件夹 src/app/heroes/,并生成了 HeroesComponent 的三个文件。

HeroesComponent 的类文件如下:


import { Component, OnInit } from '@angular/core';
  
@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

@Component 是个装饰器函数,用于为该组件指定 Angular 所需的元数据。

CLI 自动生成了三个元数据属性:

  1. selector— 组件的选择器(CSS 元素选择器)

  2. templateUrl— 组件模板文件的位置。

  3. styleUrls— 组件私有 CSS 样式表文件的位置。

CSS 元素选择器 app-heroes 用来在父组件的模板中匹配 HTML 元素的名称,以识别出该组件。

ngOnInit 是一个生命周期钩子,Angular 在创建完组件后很快就会调用 ngOnInit。这里是放置初始化逻辑的好地方。

始终要 export 这个组件类,以便在其它地方(比如 AppModule)导入它。

添加 hero 属性

往 HeroesComponent 中添加一个 hero 属性,用来表示一个名叫 “Windstorm” 的英雄。

heroes.component.ts after:

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

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
 hero = 'Windstorm';
  constructor() { }

  ngOnInit() {
  }

}

显示英雄

打开模板文件 heroes.component.html。删除 Angular CLI 自动生成的默认内容,改为到 hero 属性的数据绑定。

{{hero}}

显示 HeroesComponent 视图

要显示 HeroesComponent 你必须把它加到壳组件 AppComponent 的模板中。

app-heroes 就是 HeroesComponent 的 元素选择器。 所以,只要把 <app-heroes> 元素添加到 AppComponent 的模板文件中就可以了,就放在标题下方。

before:

<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
  <h1>
    {{ title }}!
  </h1>
  <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://angular.io/cli">CLI Documentation</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
  </li>
</ul>

<router-outlet></router-outlet>

after:

<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
  <h1>
    {{ title }}!
  </h1>
<app-heroes></app-heroes>
  <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
</div>
<h2>Here are some links to help you start: </h2>
<ul>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://angular.io/cli">CLI Documentation</a></h2>
  </li>
  <li>
    <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
  </li>
</ul>

<router-outlet></router-outlet>

创建 Hero 类

在 src/app 文件夹中为 Hero 类创建一个文件,并添加 id 和 name 属性。

src/app/hero.ts

export class Hero {
  id: number;
  name: string;
}

回到 HeroesComponent 类,并且导入这个 Hero 类。

把组件的 hero 属性的类型重构为 Hero。 然后以 1 为 id、以 “Windstorm” 为名字初始化它。

修改后的 HeroesComponent 类应该是这样的

import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';  /**!!!***/

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };

  constructor() { }

  ngOnInit() {
  }

}

页面显示变得不正常了,因为你刚刚把 hero 从字符串改成了对象。

显示 hero 对象

修改模板中的绑定,以显示英雄的名字,并在详情中显示 id 和 name

<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>

使用 UppercasePipe 进行格式化

把 hero.name 的绑定修改成这样:

heroes.component.html :

<h2>{{hero.name| uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>

绑定表达式中的 uppercase 位于管道操作符( | )的右边,用来调用内置管道 UppercasePipe

管道 是格式化字符串、金额、日期和其它显示数据的好办法。 Angular 发布了一些内置管道,而且你还可以创建自己的管道。

编辑英雄名字

用户应该能在一个 <input> 输入框中编辑英雄的名字。

当用户输入时,这个输入框应该能同时显示修改英雄的 name 属性。 也就是说,数据流从组件类流出到屏幕,并且从屏幕流回到组件类

要想让这种数据流动自动化,就要在表单元素 <input> 和组件的 hero.name 属性之间建立双向数据绑定。

双向绑定

把模板中的英雄详情区重构成这样:

src/app/heroes/heroes.component.html 

<h2>{{hero.name| uppercase}} Details</h2>
<div>
  <label>name:
    <input [(ngModel)]="hero.name" placeholder="name">
  </label>
</div>

[(ngModel)] 是 Angular 的双向数据绑定语法。

这里把 hero.name 属性绑定到了 HTML 的 textbox 元素上,以便数据流可以双向流动:从 hero.name 属性流动到 textbox,并且从 textbox 流回到 hero.name 。

AppModule

Angular 需要知道如何把应用程序的各个部分组合到一起,以及该应用需要哪些其它文件和库。 这些信息被称为元数据(metadata)

有些元数据位于 @Component 装饰器中,你会把它加到组件类上。 另一些关键性的元数据位于 @NgModule 装饰器中。

最重要的 @NgModule 装饰器位于顶级类 AppModule 上。

Angular CLI 在创建项目的时候就在 src/app/app.module.ts 中生成了一个 AppModule 类。 这里也就是你要添加 FormsModule 的地方。

导入 FormsModule

打开 AppModule (app.module.ts) 并从 @angular/forms 库中导入 FormsModule 符号。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
@NgModule({
  declarations: [
    AppComponent,
    HeroesComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
~                              

然后把 FormsModule 添加到 @NgModule 元数据的 imports 数组中,这里是该应用所需外部模块的列表。

imports: [
  BrowserModule,
  FormsModule
],

声明 HeroesComponent

每个组件都必须声明在(且只能声明在)一个 NgModule 中。

没有声明过 HeroesComponent,可为什么本应用却正常呢?

这是因为 Angular CLI 在生成 HeroesComponent 组件的时候就自动把它加到了 AppModule 中。

打开 src/app/app.module.ts 你就会发现 HeroesComponent 已经在顶部导入过了。

import { HeroesComponent } from './heroes/heroes.component';

HeroesComponent 也已经声明在了 @NgModule.declarations 数组中。

declarations: [
  AppComponent,
  HeroesComponent
],