填寫這份《一分鐘調查》,幫我們(開發組)做得更好!去填寫Home

元件簡介

Introduction to components and templates

元件控制螢幕上被稱為檢視的一小片區域。比如,課程中的下列檢視都是由一個個元件所定義和控制的:

A component controls a patch of screen called a view. For example, individual components define and control each of the following views from the Tour of Heroes tutorial:

  • 帶有導航連結的應用根元件。

    The app root with the navigation links.

  • 英雄列表。

    The list of heroes.

  • 英雄編輯器。

    The hero editor.

你在類別中定義元件的應用邏輯,為檢視提供支援。 元件透過一些由屬性和方法組成的 API 與檢視互動。

You define a component's application logic—what it does to support the view—inside a class. The class interacts with the view through an API of properties and methods.

比如,HeroListComponent 中有一個 名為 heroes 的屬性,它儲存著一個數組的英雄資料。 HeroListComponent 還有一個 selectHero() 方法,當用戶從列表中選擇一個英雄時,它會設定 selectedHero 屬性的值。 該元件會從服務獲取英雄列表,它是一個 TypeScript 的構造器引數型屬性。本服務透過依賴注入系統提供給該元件。

For example, HeroListComponent has a heroes property that holds an array of heroes. Its selectHero() method sets a selectedHero property when the user clicks to choose a hero from that list. The component acquires the heroes from a service, which is a TypeScript parameter property on the constructor. The service is provided to the component through the dependency injection system.

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; } }
src/app/hero-list.component.ts (class)
      
      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; }
}
    

當用戶在應用中穿行時,Angular 就會建立、更新、銷燬一些元件。 你的應用可以透過一些可選的生命週期鉤子(比如 ngOnInit())來在每個特定的時機採取行動。

Angular creates, updates, and destroys components as the user moves through the application. Your app can take action at each moment in this lifecycle through optional lifecycle hooks, like ngOnInit().

元件的元資料

Component metadata

Metadata

@Component 裝飾器會指出緊隨其後的那個類別是個元件類別,並為其指定元資料。 在下面的範例程式碼中,你可以看到 HeroListComponent 只是一個普通類別,完全沒有 Angular 特有的標記或語法。 直到給它加上了 @Component 裝飾器,它才變成了元件。

The @Component decorator identifies the class immediately below it as a component class, and specifies its metadata. In the example code below, you can see that HeroListComponent is just a class, with no special Angular notation or syntax at all. It's not a component until you mark it as one with the @Component decorator.

元件的元資料告訴 Angular 到哪裡獲取它需要的主要構成要素,以建立和展示這個元件及其檢視。 具體來說,它把一個範本(無論是直接內聯在程式碼中還是參考的外部檔案)和該元件關聯起來。 該元件及其範本,共同描述了一個檢視

The metadata for a component tells Angular where to get the major building blocks that it needs to create and present the component and its view. In particular, it associates a template with the component, either directly with inline code, or by reference. Together, the component and its template describe a view.

除了包含或指向範本之外,@Component 的元資料還會配置要如何在 HTML 中參考該元件,以及該元件需要哪些服務等等。

In addition to containing or pointing to the template, the @Component metadata configures, for example, how the component can be referenced in HTML and what services it requires.

下面的例子中就是 HeroListComponent 的基礎元資料:

Here's an example of basic metadata for HeroListComponent.

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

這個例子展示了一些最常用的 @Component 配置選項:

This example shows some of the most useful @Component configuration options:

  • selector:是一個 CSS 選擇器,它會告訴 Angular,一旦在範本 HTML 中找到了這個選擇器對應的標籤,就建立並插入該元件的一個實例。 比如,如果應用的 HTML 中包含 <app-hero-list></app-hero-list>,Angular 就會在這些標籤中插入一個 HeroListComponent 實例的檢視。

    selector: A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. For example, if an app's HTML contains <app-hero-list></app-hero-list>, then Angular inserts an instance of the HeroListComponent view between those tags.

  • templateUrl:該元件的 HTML 範本檔案相對於這個元件檔案的地址。 另外,你還可以用 template 屬性的值來提供內聯的 HTML 範本。 這個範本定義了該元件的宿主檢視

    templateUrl: The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the template property. This template defines the component's host view.

  • providers:當前元件所需的服務提供者的一個數組。在這個例子中,它告訴 Angular 該如何提供一個 HeroService 實例,以獲取要顯示的英雄列表。

    providers: An array of providers for services that the component requires. In the example, this tells Angular how to provide the HeroService instance that the component's constructor uses to get the list of heroes to display.

範本與檢視

Templates and views

Template

你要透過元件的配套範本來定義其檢視。範本就是一種 HTML,它會告訴 Angular 如何渲染該元件。

You define a component's view with its companion template. A template is a form of HTML that tells Angular how to render the component.

檢視通常會分層次進行組織,讓你能以 UI 分區或頁面為單位進行修改、顯示或隱藏。 與元件直接關聯的範本會定義該元件的宿主檢視。該元件還可以定義一個帶層次結構的檢視,它包含一些內嵌的檢視作為其它元件的宿主。

Views are typically arranged hierarchically, allowing you to modify or show and hide entire UI sections or pages as a unit. The template immediately associated with a component defines that component's host view. The component can also define a view hierarchy, which contains embedded views, hosted by other components.

帶層次結構的檢視可以包含同一模組(NgModule)中元件的檢視,也可以(而且經常會)包含其它模組中定義的元件的檢視。

A view hierarchy can include views from components in the same NgModule, but it also can (and often does) include views from components that are defined in different NgModules.

範本語法

Template syntax

範本很像標準的 HTML,但是它還包含 Angular 的範本語法,這些範本語法可以根據你的應用邏輯、應用狀態和 DOM 資料來修改這些 HTML。 你的範本可以使用資料繫結來協調應用和 DOM 中的資料,使用管道在顯示出來之前對其進行轉換,使用指令來把程式邏輯應用到要顯示的內容上。

A template looks like regular HTML, except that it also contains Angular template syntax, which alters the HTML based on your app's logic and the state of app and DOM data. Your template can use data binding to coordinate the app and DOM data, pipes to transform data before it is displayed, and directives to apply app logic to what gets displayed.

比如,下面是本課程中 HeroListComponent 的範本:

For example, here is a template for the Tutorial's 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>
src/app/hero-list.component.html
      
      <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>
    

這個範本使用了典型的 HTML 元素,比如 <h2><p>,還包括一些 Angular 的範本語法元素,如 *ngFor{{hero.name}}click[hero]<app-hero-detail>。這些範本語法元素告訴 Angular 該如何根據程式邏輯和資料在螢幕上渲染 HTML。

This template uses typical HTML elements like <h2> and <p>, and also includes Angular template-syntax elements, *ngFor, {{hero.name}}, (click), [hero], and <app-hero-detail>. The template-syntax elements tell Angular how to render the HTML to the screen, using program logic and data.

  • *ngFor 指令告訴 Angular 在一個列表上進行迭代。

    The *ngFor directive tells Angular to iterate over a list.

  • {{hero.name}}(click)[hero] 把程式資料繫結到及繫結回 DOM,以響應使用者的輸入。更多內容參閱稍後的資料繫結部分。

    {{hero.name}}, (click), and [hero] bind program data to and from the DOM, responding to user input. See more about data binding below.

  • 範本中的 <app-hero-detail> 標籤是一個代表新元件 HeroDetailComponent 的元素。 HeroDetailComponent(程式碼略)定義了 HeroListComponent 的英雄詳情子檢視。 注意觀察像這樣的自訂元件是如何與原生 HTML 元素無縫的混合在一起的。

    The <app-hero-detail> tag in the example is an element that represents a new component, HeroDetailComponent. HeroDetailComponent (code not shown) defines the hero-detail child view of HeroListComponent. Notice how custom components like this mix seamlessly with native HTML in the same layouts.

資料繫結

Data binding

如果沒有框架,你就要自己負責把資料值推送到 HTML 控制元件中,並把來自使用者的響應轉換成動作和對值的更新。 手動寫這種資料推拉邏輯會很枯燥、容易出錯,難以閱讀 —— 有前端 JavaScript 開發經驗的程式設計師一定深有體會。

Without a framework, you would be responsible for pushing data values into the HTML controls and turning user responses into actions and value updates. Writing such push and pull logic by hand is tedious, error-prone, and a nightmare to read, as any experienced front-end JavaScript programmer can attest.

Angular 支援雙向資料繫結,這是一種對範本中的各個部件與元件中的各個部件進行協調的機制。 往範本 HTML 中新增繫結標記可以告訴 Angular 該如何連線它們。

Angular supports two-way data binding, a mechanism for coordinating the parts of a template with the parts of a component. Add binding markup to the template HTML to tell Angular how to connect both sides.

下圖顯示了資料繫結標記的四種形式。每種形式都有一個方向 —— 從元件到 DOM、從 DOM 到元件或雙向。

The following diagram shows the four forms of data binding markup. Each form has a direction: to the DOM, from the DOM, or both.

這個來自 HeroListComponent 範本中的例子使用了其中的三種形式:

This example from the HeroListComponent template uses three of these forms.

<li>{{hero.name}}</li> <app-hero-detail [hero]="selectedHero"></app-hero-detail> <li (click)="selectHero(hero)"></li>
src/app/hero-list.component.html (binding)
      
      <li>{{hero.name}}</li>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<li (click)="selectHero(hero)"></li>
    
  • {{hero.name}} 這個插值<li> 標籤中顯示元件的 hero.name 屬性的值。

    The {{hero.name}} interpolation displays the component's hero.name property value within the <li> element.

  • [hero]屬性繫結把父元件 HeroListComponentselectedHero 的值傳到子元件 HeroDetailComponenthero 屬性中。

    The [hero] property binding passes the value of selectedHero from the parent HeroListComponent to the hero property of the child HeroDetailComponent.

  • 當用戶點選某個英雄的名字時,(click) 事件繫結會呼叫元件的 selectHero 方法。

    The (click) event binding calls the component's selectHero method when the user clicks a hero's name.

雙向資料繫結(主要用於範本驅動表單中),它會把屬性繫結和事件繫結組合成一種單獨的寫法。下面這個來自 HeroDetailComponent 範本中的例子透過 ngModel 指令使用了雙向資料繫結:

Two-way data binding (used mainly in template-driven forms) combines property and event binding in a single notation. Here's an example from the HeroDetailComponent template that uses two-way data binding with the ngModel directive.

<input [(ngModel)]="hero.name">
src/app/hero-detail.component.html (ngModel)
      
      <input [(ngModel)]="hero.name">
    

在雙向繫結中,資料屬性值透過屬性繫結從元件流到輸入框。使用者的修改透過事件繫結流回元件,把屬性值設定為最新的值。

In two-way binding, a data property value flows to the input box from the component as with property binding. The user's changes also flow back to the component, resetting the property to the latest value, as with event binding.

Angular 在每個 JavaScript 事件迴圈中處理所有的資料繫結,它會從元件樹的根部開始,遞迴處理全部子元件。

Angular processes all data bindings once for each JavaScript event cycle, from the root of the application component tree through all child components.

資料繫結在範本及其元件之間的通訊中扮演了非常重要的角色,它對於父元件和子元件之間的通訊也同樣重要。

Data binding plays an important role in communication between a template and its component, and is also important for communication between parent and child components.

管道

Pipes

Angular 的管道可以讓你在範本中宣告顯示值的轉換邏輯。 帶有 @Pipe 裝飾器的類別中會定義一個轉換函式,用來把輸入值轉換成供檢視顯示用的輸出值。

Angular pipes let you declare display-value transformations in your template HTML. A class with the @Pipe decorator defines a function that transforms input values to output values for display in a view.

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

Angular defines various pipes, such as the date pipe and currency pipe; for a complete list, see the Pipes API list. You can also define new pipes.

要在 HTML 範本中指定值的轉換方式,請使用 管道運算子 (|)

To specify a value transformation in an HTML template, use the pipe operator (|).

{{interpolated_value | pipe_name}}

你可以把管道串聯起來,把一個管道函式的輸出送給另一個管道函式進行轉換。 管道還能接收一些引數,來控制它該如何進行轉換。比如,你可以把要使用的日期格式傳給 date 管道:

You can chain pipes, sending the output of one pipe function to be transformed by another pipe function. A pipe can also take arguments that control how it performs its transformation. For example, you can pass the desired format to the date pipe.

<!-- 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>
      
      <!-- 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>
    

指令

Directives

Directives

Angular 的範本是動態的。當 Angular 渲染它們的時候,會根據指令給出的指示對 DOM 進行轉換。 指令就是一個帶有 @Directive() 裝飾器的類別。

Angular templates are dynamic. When Angular renders them, it transforms the DOM according to the instructions given by directives. A directive is a class with a @Directive() decorator.

元件從技術角度上說就是一個指令,但是由於元件對 Angular 應用來說非常獨特、非常重要,因此 Angular 專門定義了 @Component() 裝飾器,它使用一些面向範本的特性擴充套件了 @Directive() 裝飾器。

A component is technically a directive. However, components are so distinctive and central to Angular applications that Angular defines the @Component() decorator, which extends the @Directive() decorator with template-oriented features.

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

In addition to components, there are two other kinds of directives: structural and attribute. Angular defines a number of directives of both kinds, and you can define your own using the @Directive() decorator.

像元件一樣,指令的元資料把它所裝飾的指令類別和一個 selector 關聯起來,selector 用來把該指令插入到 HTML 中。 在範本中,指令通常作為屬性出現在元素標籤上,可能僅僅作為名字出現,也可能作為賦值目標或繫結目標出現。

Just as for components, the metadata for a directive associates the decorated class with a selector element that you use to insert it into HTML. In templates, directives typically appear within an element tag as attributes, either by name or as the target of an assignment or a binding.

結構型指令

Structural directives

結構型指令透過新增、移除或替換 DOM 元素來修改佈局。 這個範例範本使用了兩個內建的結構型指令來為要渲染的檢視新增程式邏輯:

Structural directives alter layout by adding, removing, and replacing elements in the DOM. The example template uses two built-in structural directives to add application logic to how the view is rendered.

<li *ngFor="let hero of heroes"></li> <app-hero-detail *ngIf="selectedHero"></app-hero-detail>
src/app/hero-list.component.html (structural)
      
      <li *ngFor="let hero of heroes"></li>
<app-hero-detail *ngIf="selectedHero"></app-hero-detail>
    
  • *ngFor是一個迭代器,它要求 Angular 為 heroes 列表中的每個英雄渲染出一個 <li>

    *ngForis an iterative; it tells Angular to stamp out one <li> per hero in the heroes list.

  • *ngIf是個條件語句,只有當選中的英雄存在時,它才會包含 HeroDetail 元件。

    *ngIfis a conditional; it includes the HeroDetail component only if a selected hero exists.

屬性型指令

Attribute directives

屬性型指令會修改現有元素的外觀或行為。 在範本中,它們看起來就像普通的 HTML 屬性一樣,因此得名“屬性型指令”。

Attribute directives alter the appearance or behavior of an existing element. In templates they look like regular HTML attributes, hence the name.

ngModel 指令就是屬性型指令的一個例子,它實現了雙向資料繫結。 ngModel 修改現有元素(一般是 <input>)的行為:設定其顯示屬性值,並響應 change 事件。

The ngModel directive, which implements two-way data binding, is an example of an attribute directive. ngModel modifies the behavior of an existing element (typically <input>) by setting its display value property and responding to change events.

<input [(ngModel)]="hero.name">
src/app/hero-detail.component.html (ngModel)
      
      <input [(ngModel)]="hero.name">
    

Angular 還有很多預定義指令,有些修改佈局結構(比如 ngSwitch),有些修改 DOM 元素和元件的樣子(比如 ngStylengClass)。

Angular has more pre-defined directives that either alter the layout structure (for example, ngSwitch) or modify aspects of DOM elements and components (for example, ngStyle and ngClass).

欲知詳情,參閱屬性型指令結構型指令這兩章。

Learn more in the Attribute Directives and Structural Directives guides.