Hero guide 編輯器

2020-06-29 16:41 更新

應(yīng)用程序現(xiàn)在有了基本的標(biāo)題。 接下來您要?jiǎng)?chuàng)建一個(gè)新的組件來顯示英雄信息并且把這個(gè)組件放到應(yīng)用程序的外殼里去。

創(chuàng)建英雄列表組件

使用 Angular CLI 創(chuàng)建一個(gè)名為 heroes 的新組件

ng generate component heroes

CLI 創(chuàng)建了一個(gè)新的文件夾 "src/app/heroes/",并生成了 HeroesComponent 的四個(gè)文件。其類文件如下:

Path:"app/heroes/heroes.component.ts (initial version)"

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() {
  }


}

你要從 Angular 核心庫(kù)中導(dǎo)入 Component 符號(hào),并為組件類加上 @Component 裝飾器。

@Component 是個(gè)裝飾器函數(shù),用于為該組件指定 Angular 所需的元數(shù)據(jù)。

CLI 自動(dòng)生成了三個(gè)元數(shù)據(jù)屬性:

  • selector— 組件的選擇器(CSS 元素選擇器)

  • templateUrl— 組件模板文件的位置。

  • styleUrls— 組件私有 CSS 樣式表文件的位置。

CSS 元素選擇器 app-heroes 用來在父組件的模板中匹配 HTML 元素的名稱,以識(shí)別出該組件。

ngOnInit() 是一個(gè)生命周期鉤子,Angular 在創(chuàng)建完組件后很快就會(huì)調(diào)用 ngOnInit()。這里是放置初始化邏輯的好地方。

始終要 export 這個(gè)組件類,以便在其它地方(比如 AppModule)導(dǎo)入它。

添加 hero 屬性

往 HeroesComponent 中添加一個(gè) hero 屬性,用來表示一個(gè)名叫 “W3Cschool” 的英雄。

Path:"heroes.component.ts (hero property)"

hero = 'Windstorm';

顯示英雄

打開模板文件 "heroes.component.html"。刪除 Angular CLI 自動(dòng)生成的默認(rèn)內(nèi)容,改為到 hero 屬性的數(shù)據(jù)綁定。

Path:"heroes.component.html"

{{hero}}

顯示 HeroesComponent 視圖

要顯示 HeroesComponent 你必須把它加到殼組件 AppComponent 的模板中。

別忘了,app-heroes 就是 HeroesComponent 的 元素選擇器。 所以,只要把 <app-heroes> 元素添加到 AppComponent 的模板文件中就可以了,就放在標(biāo)題下方。

Path:"src/app/app.component.html"

<h1>{{title}}</h1>
<app-heroes></app-heroes>

如果 CLI 的 ng serve 命令仍在運(yùn)行,瀏覽器就會(huì)自動(dòng)刷新,并且同時(shí)顯示出應(yīng)用的標(biāo)題和英雄的名字。

創(chuàng)建 Hero 類

真實(shí)的英雄當(dāng)然不止一個(gè)名字。

src/app 文件夾中為 Hero 類創(chuàng)建一個(gè)文件,并添加 id 和 name 屬性。

Path:"src/app/hero.ts"

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

回到 HeroesComponent 類,并且導(dǎo)入這個(gè) Hero 類。

把組件的 hero 屬性的類型重構(gòu)為 Hero。 然后以 1 為 id、以 “W3Cschool” 為名字初始化它。

修改后的 HeroesComponent 類如下:

Path:"src/app/heroes/heroes.component.ts"

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() {
  }


}

頁(yè)面顯示變得不正常了,因?yàn)槟銊倓偘?hero 從字符串改成了對(duì)象。

顯示 hero 對(duì)象

修改模板中的綁定,以顯示英雄的名字,并在詳情中顯示 id 和 name,就像這樣:

Path:"heroes.component.html (HeroesComponent's template)"

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

瀏覽器自動(dòng)刷新,并顯示這位英雄的信息。

使用 UppercasePipe 進(jìn)行格式化

把 hero.name 的綁定修改成這樣:

Path:"src/app/heroes/heroes.component.html"

<h2>{{hero.name | uppercase}} Details</h2>

瀏覽器刷新了。現(xiàn)在,英雄的名字顯示成了大寫字母。

綁定表達(dá)式中的 uppercase 位于管道操作符( | )的右邊,用來調(diào)用內(nèi)置管道 UppercasePipe。

管道 是格式化字符串、金額、日期和其它顯示數(shù)據(jù)的好辦法。 Angular 發(fā)布了一些內(nèi)置管道,而且你還可以創(chuàng)建自己的管道。

編輯英雄名字

用戶應(yīng)該能在一個(gè) <input> 輸入框中編輯英雄的名字。

當(dāng)用戶輸入時(shí),這個(gè)輸入框應(yīng)該能同時(shí)顯示和修改英雄的 name 屬性。 也就是說,數(shù)據(jù)流從組件類流出到屏幕,并且從屏幕流回到組件類。

要想讓這種數(shù)據(jù)流動(dòng)自動(dòng)化,就要在表單元素 <input> 和組件的 hero.name 屬性之間建立雙向數(shù)據(jù)綁定。

雙向綁定

把模板中的英雄詳情區(qū)重構(gòu)成這樣:

Path:"src/app/heroes/heroes.component.html (HeroesComponent's template)"

<div>
  <label>name:
    <input [(ngModel)]="hero.name" placeholder="name"/>
  </label>
</div>

[(ngModel)] 是 Angular 的雙向數(shù)據(jù)綁定語(yǔ)法。

這里把 hero.name 屬性綁定到了 HTML 的 textbox 元素上,以便數(shù)據(jù)流可以雙向流動(dòng):從 hero.name 屬性流動(dòng)到 textbox,并且從 textbox 流回到 hero.name。

缺少 FormsModule

注意,當(dāng)你加上 [(ngModel)] 之后這個(gè)應(yīng)用無(wú)法工作了。

打開瀏覽器的開發(fā)工具,就會(huì)在控制臺(tái)中看到如下信息:

Template parse errors:
Can't bind to 'ngModel' since it isn't a known property of 'input'.

雖然 ngModel 是一個(gè)有效的 Angular 指令,不過它在默認(rèn)情況下是不可用的。

它屬于一個(gè)可選模塊 FormsModule,你必須自行添加此模塊才能使用該指令。

AppModule

Angular 需要知道如何把應(yīng)用程序的各個(gè)部分組合到一起,以及該應(yīng)用需要哪些其它文件和庫(kù)。 這些信息被稱為元數(shù)據(jù)(metadata)。

有些元數(shù)據(jù)位于 @Component 裝飾器中,你會(huì)把它加到組件類上。 另一些關(guān)鍵性的元數(shù)據(jù)位于 @NgModule 裝飾器中。

最重要的 @NgModule 裝飾器位于頂層類 AppModule 上。

Angular CLI 在創(chuàng)建項(xiàng)目的時(shí)候就在 "src/app/app.module.ts" 中生成了一個(gè) AppModule 類。 這里也就是你要添加 FormsModule 的地方。

導(dǎo)入 FormsModule

打開 AppModule (app.module.ts) 并從 @angular/forms 庫(kù)中導(dǎo)入 FormsModule 符號(hào)。

Path:"app.module.ts (FormsModule symbol import)"

import { FormsModule } from '@angular/forms'; // <-- NgModel lives here

然后把 FormsModule 添加到 @NgModule 元數(shù)據(jù)的 imports 數(shù)組中,這里是該應(yīng)用所需外部模塊的列表。

Path:"app.module.ts (@NgModule imports)"

imports: [
  BrowserModule,
  FormsModule
],

刷新瀏覽器,應(yīng)用又能正常工作了。你可以編輯英雄的名字,并且會(huì)看到這個(gè)改動(dòng)立刻體現(xiàn)在這個(gè)輸入框上方的 <h2> 中。

聲明 HeroesComponent

每個(gè)組件都必須聲明在(且只能聲明在)一個(gè) NgModule 中。

你沒有聲明過 HeroesComponent,可為什么本應(yīng)用卻正常呢?

這是因?yàn)?Angular CLI 在生成 HeroesComponent 組件的時(shí)候就自動(dòng)把它加到了 AppModule 中。

打開 "src/app/app.module.ts" 你就會(huì)發(fā)現(xiàn) HeroesComponent 已經(jīng)在頂部導(dǎo)入過了。

Path:"src/app/app.module.ts"

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

HeroesComponent 也已經(jīng)聲明在了 @NgModule.declarations 數(shù)組中。

Path:"src/app/app.module.ts"

declarations: [
  AppComponent,
  HeroesComponent
],

注:
AppModule 聲明了應(yīng)用中的所有組件,AppComponent 和 HeroesComponent。

Final code review

本篇設(shè)計(jì)的代碼如下:

  1. Path:"src/app/heroes/heroes.component.ts"

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() {
  }


}

  1. Path:"src/app/heroes/heroes.component.html"

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

  1. Path:"src/app/app.module.ts"

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here


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


@NgModule({
  declarations: [
    AppComponent,
    HeroesComponent
  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

  1. Path:"src/app/app.component.ts"

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


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Tour of Heroes';
}

  1. Path:"src/app/app.component.html"

<h1>{{title}}</h1>
<app-heroes></app-heroes>

  1. Path:"src/app/hero.ts"

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

總結(jié)

  • 您使用 CLI 創(chuàng)建了第二個(gè)組件 HeroesComponent。

  • 您把 HeroesComponent 添加到了殼組件 AppComponent 中,以便顯示它。

  • 您使用 UppercasePipe 來格式化英雄的名字。

  • 您用 ngModel 指令實(shí)現(xiàn)了雙向數(shù)據(jù)綁定。

  • 您知道了 AppModule。

  • 您把 FormsModule 導(dǎo)入了 AppModule,以便 Angular 能識(shí)別并應(yīng)用 ngModel 指令。

  • 您知道了把組件聲明到 AppModule 是很重要的,并認(rèn)識(shí)到 CLI 會(huì)自動(dòng)幫你聲明它。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)