Angular9 組件簡(jiǎn)介

2020-06-28 17:05 更新

組件控制屏幕上被稱為視圖的一小片區(qū)域。比如,教程中的下列視圖都是由一個(gè)個(gè)組件所定義和控制的:

  • 帶有導(dǎo)航鏈接的應(yīng)用根組件。

  • 英雄列表。

  • 英雄編輯器。

你在類中定義組件的應(yīng)用邏輯,為視圖提供支持。 組件通過一些由屬性和方法組成的 API 與視圖交互。

比如,HeroListComponent 中有一個(gè) 名為 heroes 的屬性,它儲(chǔ)存著一個(gè)數(shù)組的英雄數(shù)據(jù)。 HeroListComponent 還有一個(gè) selectHero() 方法,當(dāng)用戶從列表中選擇一個(gè)英雄時(shí),它會(huì)設(shè)置 selectedHero 屬性的值。 該組件會(huì)從服務(wù)獲取英雄列表,它是一個(gè) TypeScript 的構(gòu)造器參數(shù)型屬性。本服務(wù)通過依賴注入系統(tǒng)提供給該組件。

export class HeroListComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;


  constructor(private service: HeroService) { }


  ngOnInit() {
    this.heroes = this.service.getHeroes();
  }


  selectHero(hero: Hero) { this.selectedHero = hero; }
}

當(dāng)用戶在應(yīng)用中穿行時(shí),Angular 就會(huì)創(chuàng)建、更新、銷毀一些組件。 你的應(yīng)用可以通過一些可選的生命周期鉤子(比如 ngOnInit())來在每個(gè)特定的時(shí)機(jī)采取行動(dòng)。

組件的元數(shù)據(jù)

@Component 裝飾器會(huì)指出緊隨其后的那個(gè)類是個(gè)組件類,并為其指定元數(shù)據(jù)。 在下面的范例代碼中,你可以看到 HeroListComponent 只是一個(gè)普通類,完全沒有 Angular 特有的標(biāo)記或語法。 直到給它加上了 @Component 裝飾器,它才變成了組件。

組件的元數(shù)據(jù)告訴 Angular 到哪里獲取它需要的主要構(gòu)造塊,以創(chuàng)建和展示這個(gè)組件及其視圖。 具體來說,它把一個(gè)模板(無論是直接內(nèi)聯(lián)在代碼中還是引用的外部文件)和該組件關(guān)聯(lián)起來。 該組件及其模板,共同描述了一個(gè)視圖。

除了包含或指向模板之外,@Component 的元數(shù)據(jù)還會(huì)配置要如何在 HTML 中引用該組件,以及該組件需要哪些服務(wù)等等。

下面的例子中就是 HeroListComponent 的基礎(chǔ)元數(shù)據(jù):

@Component({
  selector:    'app-hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

這個(gè)例子展示了一些最常用的 @Component 配置選項(xiàng):

  • selector:是一個(gè) CSS 選擇器,它會(huì)告訴 Angular,一旦在模板 HTML 中找到了這個(gè)選擇器對(duì)應(yīng)的標(biāo)簽,就創(chuàng)建并插入該組件的一個(gè)實(shí)例。 比如,如果應(yīng)用的 HTML 中包含 <app-hero-list></app-hero-list>,Angular 就會(huì)在這些標(biāo)簽中插入一個(gè) HeroListComponent 實(shí)例的視圖。

  • templateUrl:該組件的 HTML 模板文件相對(duì)于這個(gè)組件文件的地址。 另外,你還可以用 template 屬性的值來提供內(nèi)聯(lián)的 HTML 模板。 這個(gè)模板定義了該組件的宿主視圖。

  • providers:當(dāng)前組件所需的服務(wù)提供者的一個(gè)數(shù)組。在這個(gè)例子中,它告訴 Angular 該如何提供一個(gè) HeroService 實(shí)例,以獲取要顯示的英雄列表。

模板與視圖

你要通過組件的配套模板來定義其視圖。模板就是一種 HTML,它會(huì)告訴 Angular 如何渲染該組件。

視圖通常會(huì)分層次進(jìn)行組織,讓你能以 UI 分區(qū)或頁(yè)面為單位進(jìn)行修改、顯示或隱藏。 與組件直接關(guān)聯(lián)的模板會(huì)定義該組件的宿主視圖。該組件還可以定義一個(gè)帶層次結(jié)構(gòu)的視圖,它包含一些內(nèi)嵌的視圖作為其它組件的宿主。

帶層次結(jié)構(gòu)的視圖可以包含同一模塊(NgModule)中組件的視圖,也可以(而且經(jīng)常會(huì))包含其它模塊中定義的組件的視圖。

模板語法

模板很像標(biāo)準(zhǔn)的 HTML,但是它還包含 Angular 的模板語法,這些模板語法可以根據(jù)你的應(yīng)用邏輯、應(yīng)用狀態(tài)和 DOM 數(shù)據(jù)來修改這些 HTML。 你的模板可以使用數(shù)據(jù)綁定來協(xié)調(diào)應(yīng)用和 DOM 中的數(shù)據(jù),使用管道在顯示出來之前對(duì)其進(jìn)行轉(zhuǎn)換,使用指令來把程序邏輯應(yīng)用到要顯示的內(nèi)容上。

比如,下面是本教程中 HeroListComponent 的模板:

<h2>Hero List</h2>


<p><i>Pick a hero from the list</i></p>
<ul>
  <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
    {{hero.name}}
  </li>
</ul>


<app-hero-detail *ngIf="selectedHero" [hero]="selectedHero"></app-hero-detail>

這個(gè)模板使用了典型的 HTML 元素,比如 <h2><p>,還包括一些 Angular 的模板語法元素,如 *ngFor,{{hero.name}},click、[hero]<app-hero-detail>。這些模板語法元素告訴 Angular 該如何根據(jù)程序邏輯和數(shù)據(jù)在屏幕上渲染 HTML。

  • *ngFor 指令告訴 Angular 在一個(gè)列表上進(jìn)行迭代。

  • {{hero.name}}、(click)[hero] 把程序數(shù)據(jù)綁定到及綁定回 DOM,以響應(yīng)用戶的輸入。更多內(nèi)容參見稍后的數(shù)據(jù)綁定部分。

  • 模板中的 <app-hero-detail> 標(biāo)簽是一個(gè)代表新組件 HeroDetailComponent 的元素。 HeroDetailComponent(代碼略)定義了 HeroListComponent 的英雄詳情子視圖。 注意觀察像這樣的自定義組件是如何與原生 HTML 元素?zé)o縫的混合在一起的。

數(shù)據(jù)綁定

如果沒有框架,你就要自己負(fù)責(zé)把數(shù)據(jù)值推送到 HTML 控件中,并把來自用戶的響應(yīng)轉(zhuǎn)換成動(dòng)作和對(duì)值的更新。 手動(dòng)寫這種數(shù)據(jù)推拉邏輯會(huì)很枯燥、容易出錯(cuò),難以閱讀 —— 有前端 JavaScript 開發(fā)經(jīng)驗(yàn)的程序員一定深有體會(huì)。

Angular 支持雙向數(shù)據(jù)綁定,這是一種對(duì)模板中的各個(gè)部件與組件中的各個(gè)部件進(jìn)行協(xié)調(diào)的機(jī)制。 往模板 HTML 中添加綁定標(biāo)記可以告訴 Angular 該如何連接它們。

下圖顯示了數(shù)據(jù)綁定標(biāo)記的四種形式。每種形式都有一個(gè)方向 —— 從組件到 DOM、從 DOM 到組件或雙向。

這個(gè)來自 HeroListComponent 模板中的例子展示了其中的三種形式:

<li>{{hero.name}}</li>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<li (click)="selectHero(hero)"></li>

  • {{hero.name}} 這個(gè)插值在 <li> 標(biāo)簽中顯示組件的 hero.name 屬性的值。

  • [hero]屬性綁定把父組件 HeroListComponent 的 selectedHero 的值傳到子組件 HeroDetailComponent 的 hero 屬性中。

  • 當(dāng)用戶點(diǎn)擊某個(gè)英雄的名字時(shí),(click) 事件綁定會(huì)調(diào)用組件的 selectHero 方法。

雙向數(shù)據(jù)綁定(主要用于模板驅(qū)動(dòng)表單中),它會(huì)把屬性綁定和事件綁定組合成一種單獨(dú)的寫法。下面這個(gè)來自 HeroDetailComponent 模板中的例子通過 ngModel 指令使用了雙向數(shù)據(jù)綁定:

<input [(ngModel)]="hero.name">

在雙向綁定中,數(shù)據(jù)屬性值通過屬性綁定從組件流到輸入框。用戶的修改通過事件綁定流回組件,把屬性值設(shè)置為最新的值。

Angular 在每個(gè) JavaScript 事件循環(huán)中處理所有的數(shù)據(jù)綁定,它會(huì)從組件樹的根部開始,遞歸處理全部子組件。

數(shù)據(jù)綁定在模板及其組件之間的通訊中扮演了非常重要的角色,它對(duì)于父組件和子組件之間的通訊也同樣重要。

管道

Angular 的管道可以讓你在模板中聲明顯示值的轉(zhuǎn)換邏輯。 帶有 @Pipe 裝飾器的類中會(huì)定義一個(gè)轉(zhuǎn)換函數(shù),用來把輸入值轉(zhuǎn)換成供視圖顯示用的輸出值。

Angular 自帶了很多管道,比如 date 管道和 currency 管道,完整的列表參見 Pipes API 列表。你也可以自己定義一些新管道。

要在 HTML 模板中指定值的轉(zhuǎn)換方式,請(qǐng)使用 管道操作符 (|)。

{{interpolated_value | pipe_name}}

你可以把管道串聯(lián)起來,把一個(gè)管道函數(shù)的輸出送給另一個(gè)管道函數(shù)進(jìn)行轉(zhuǎn)換。 管道還能接收一些參數(shù),來控制它該如何進(jìn)行轉(zhuǎn)換。比如,你可以把要使用的日期格式傳給 date 管道:

<!-- Default format: output 'Jun 15, 2015'-->


 <p>Today is {{today | date}}</p>


<!-- fullDate format: output 'Monday, June 15, 2015'-->


<p>The date is {{today | date:'fullDate'}}</p>


 <!-- shortTime format: output '9:43 AM'-->


 <p>The time is {{today | date:'shortTime'}}</p>

指令

Angular 的模板是動(dòng)態(tài)的。當(dāng) Angular 渲染它們的時(shí)候,會(huì)根據(jù)指令給出的指示對(duì) DOM 進(jìn)行轉(zhuǎn)換。 指令就是一個(gè)帶有 @Directive() 裝飾器的類。

組件從技術(shù)角度上說就是一個(gè)指令,但是由于組件對(duì) Angular 應(yīng)用來說非常獨(dú)特、非常重要,因此 Angular 專門定義了 @Component() 裝飾器,它使用一些面向模板的特性擴(kuò)展了 @Directive() 裝飾器。

除組件外,還有兩種指令:結(jié)構(gòu)型指令和屬性型指令。 Angular 本身定義了一系列這兩種類型的指令,你也可以使用 @Directive() 裝飾器來定義自己的指令。

像組件一樣,指令的元數(shù)據(jù)把它所裝飾的指令類和一個(gè) selector 關(guān)聯(lián)起來,selector 用來把該指令插入到 HTML 中。 在模板中,指令通常作為屬性出現(xiàn)在元素標(biāo)簽上,可能僅僅作為名字出現(xiàn),也可能作為賦值目標(biāo)或綁定目標(biāo)出現(xiàn)。

1. 結(jié)構(gòu)型指令

結(jié)構(gòu)型指令通過添加、移除或替換 DOM 元素來修改布局。 這個(gè)范例模板使用了兩個(gè)內(nèi)置的結(jié)構(gòu)型指令來為要渲染的視圖添加程序邏輯:

<li *ngFor="let hero of heroes"></li>
<app-hero-detail *ngIf="selectedHero"></app-hero-detail>

  • *ngFor 是一個(gè)迭代器,它要求 Angular 為 heroes 列表中的每個(gè)英雄渲染出一個(gè) <li>。

  • *ngIf 是個(gè)條件語句,只有當(dāng)選中的英雄存在時(shí),它才會(huì)包含 HeroDetail 組件。

2. 屬性型指令

屬性型指令會(huì)修改現(xiàn)有元素的外觀或行為。 在模板中,它們看起來就像普通的 HTML 屬性一樣,因此得名“屬性型指令”。

ngModel 指令就是屬性型指令的一個(gè)例子,它實(shí)現(xiàn)了雙向數(shù)據(jù)綁定。 ngModel 修改現(xiàn)有元素(一般是 <input>)的行為:設(shè)置其顯示屬性值,并響應(yīng) change 事件。

<input [(ngModel)]="hero.name">

注:
- Angular 還有很多預(yù)定義指令,有些修改布局結(jié)構(gòu)(比如 ngSwitch),有些修改 DOM 元素和組件的樣子(比如 ngStylengClass)。
- 參考 [Angular9 結(jié)構(gòu)型指令]() 和 [Angular9 屬性型指令]() 以了解 Angular 兩種指令類型。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)