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

內建指令

Built-in directives

指令是為 Angular 應用程式中的元素新增額外行為的類別。使用 Angular 的內建指令,你可以管理表單、列表、樣式以及要讓使用者看到的任何內容。

Directives are classes that add additional behavior to elements in your Angular applications. With Angular's built-in directives, you can manage forms, lists, styles, and what users see.

要檢視包含本指南中程式碼的可工作範例,請參閱現場演練 / 下載範例

See the現場演練 / 下載範例for a working example containing the code snippets in this guide.

Angular 指令的不同型別如下:

The different types of Angular directives are as follows:

  1. 元件 —— 帶有範本的指令。這種指令型別是最常見的指令型別。

    Components—directives with a template. This type of directive is the most common directive type.

  2. 屬性型指令 —— 更改元素、元件或其他指令的外觀或行為的指令。

    Attribute directives—directives that change the appearance or behavior of an element, component, or another directive.

  3. 結構型指令 —— 透過新增和刪除 DOM 元素來更改 DOM 佈局的指令。

    Structural directives—directives that change the DOM layout by adding and removing DOM elements.

本指南涵蓋了內建的屬性型指令結構型指令

This guide covers built-in attribute directives and structural directives.

內建屬性型指令

Built-in attribute directives

屬性型指令會監聽並修改其它 HTML 元素和元件的行為、Attribute 和 Property。

Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components.

許多 NgModule(例如 RouterModuleFormsModule都定義了自己的屬性型指令。最常見的屬性型指令如下:

Many NgModules such as the RouterModuleand the FormsModuledefine their own attribute directives. The most common attribute directives are as follows:

  • NgClass—— 新增和刪除一組 CSS 類別。

    NgClass—adds and removes a set of CSS classes.

  • NgStyle—— 新增和刪除一組 HTML 樣式。

    NgStyle—adds and removes a set of HTML styles.

  • NgModel—— 將資料雙向繫結新增到 HTML 表單元素。

    NgModel—adds two-way data binding to an HTML form element.

NgClass 新增和刪除類別

Adding and removing classes with NgClass

ngClass 同時新增或刪除多個 CSS 類別。

You can add or remove multiple CSS classes simultaneously with ngClass.

要新增或刪除單個類別,請使用類別繫結而不是 NgClass

To add or remove a single class, use class binding rather than NgClass.

NgClass 與表示式一起使用

Using NgClass with an expression

在要設定樣式的元素上,新增 [ngClass] 並將其設定為等於某個表示式。在這裡,是在 app.component.ts 中將 isSpecial 設定為布林值 true。因為 isSpecial 為 true,所以 ngClass 就會把 special 類別應用於此 <div> 上。

On the element you'd like to style, add [ngClass] and set it equal to an expression. In this case, isSpecial is a boolean set to true in app.component.ts. Because isSpecial is true, ngClass applies the class of special to the <div>.

src/app/app.component.html
      
      <!-- toggle the "special" class on/off with a property -->
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
    

NgClass 與方法一起使用

Using NgClass with a method

  1. 要將 NgClass 與方法一起使用,請將方法新增到元件類別中。在下面的示例中,setCurrentClasses() 使用一個物件來設定屬性 currentClasses,該物件根據另外三個元件屬性為 truefalse 來新增或刪除三個 CSS 類別。

    To use NgClass with a method, add the method to the component class. In the following example, setCurrentClasses() sets the property currentClasses with an object that adds or removes three classes based on the true or false state of three other component properties.

    該物件的每個鍵(key)都是一個 CSS 類別名稱。如果鍵為 true,則 ngClass 新增該類別。如果鍵為 false,則 ngClass 刪除該類別。

    Each key of the object is a CSS class name. If a key is true, ngClass adds the class. If a key is false, ngClass removes the class.

src/app/app.component.ts
      
      currentClasses: Record<string, boolean> = {};
/* . . . */
  setCurrentClasses() {
    // CSS classes: added/removed per current state of component properties
    this.currentClasses =  {
      saveable: this.canSave,
      modified: !this.isUnchanged,
      special:  this.isSpecial
    };
  }
    
  1. 在範本中,把 ngClass 屬性繫結到 currentClasses,根據它來設定此元素的 CSS 類別:

    In the template, add the ngClass property binding to currentClasses to set the element's classes:

src/app/app.component.html
      
      <div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
    

在這個例子中,Angular 會在初始化以及發生更改的情況下應用這些類別。完整的示例會在 ngOnInit() 中進行初始化以及透過單擊按鈕更改相關屬性時呼叫 setCurrentClasses()。這些步驟對於實現 ngClass 不是必需的。有關更多資訊,請參見現場演練 / 下載範例中的 app.component.tsapp.component.html

For this use case, Angular applies the classes on initialization and in case of changes. The full example calls setCurrentClasses() initially with ngOnInit() and when the dependent properties change through a button click. These steps are not necessary to implement ngClass. For more information, see the現場演練 / 下載範例 app.component.ts and app.component.html.

NgStyle 設定內聯樣式

Setting inline styles with NgStyle

你可以使用 NgStyle 根據元件的狀態同時設定多個內聯樣式。

You can use NgStyle to set multiple inline styles simultaneously, based on the state of the component.

  1. 要使用 NgStyle,請向元件類別新增一個方法。

    To use NgStyle, add a method to the component class.

    在下面的例子中,setCurrentStyles() 方法基於該元件另外三個屬性的狀態,用一個定義了三個樣式的物件設定了 currentStyles 屬性。

    In the following example, setCurrentStyles() sets the property currentStyles with an object that defines three styles, based on the state of three other component properties.

src/app/app.component.ts
      
      currentStyles: Record<string, string> = {};
/* . . . */
  setCurrentStyles() {
    // CSS styles: set per current state of component properties
    this.currentStyles = {
      'font-style':  this.canSave      ? 'italic' : 'normal',
      'font-weight': !this.isUnchanged ? 'bold'   : 'normal',
      'font-size':   this.isSpecial    ? '24px'   : '12px'
    };
  }
    
  1. 要設定元素的樣式,請將 ngStyle 屬性繫結到 currentStyles

    To set the element's styles, add an ngStyle property binding to currentStyles.

src/app/app.component.html
      
      <div [ngStyle]="currentStyles">
  This div is initially italic, normal weight, and extra large (24px).
</div>
    

在這個例子中,Angular 會在初始化以及發生更改的情況下應用這些類別。完整的示例會在 ngOnInit() 中進行初始化以及透過單擊按鈕更改相關屬性時呼叫 setCurrentClasses()。這些步驟對於實現 ngClass 不是必需的。有關更多資訊,請參見現場演練 / 下載範例中的 app.component.tsapp.component.html

For this use case, Angular applies the styles upon initialization and in case of changes. To do this, the full example calls setCurrentStyles() initially with ngOnInit() and when the dependent properties change through a button click. However, these steps are not necessary to implement ngStyle on its own. See the現場演練 / 下載範例 app.component.ts and app.component.html for this optional implementation.

ngModel 顯示和更新屬性

Displaying and updating properties with ngModel

你可以使用 NgModel 指令顯示資料屬性,並在使用者進行更改時更新該屬性。

You can use the NgModel directive to display a data property and update that property when the user makes changes.

  1. 匯入 FormsModule,並將其新增到 NgModule 的 imports 列表中。

    Import FormsModule and add it to the NgModule's imports list.

src/app/app.module.ts (FormsModule import)
      
      import { FormsModule } from '@angular/forms'; // <--- JavaScript import from Angular
/* . . . */
@NgModule({
/* . . . */

  imports: [
    BrowserModule,
    FormsModule // <--- import into the NgModule
  ],
/* . . . */
})
export class AppModule { }
    
  1. 在 HTML 的 <form> 元素上新增 [(ngModel)] 繫結,並將其設定為等於此屬性,這裡是 name

    Add an [(ngModel)] binding on an HTML <form> element and set it equal to the property, here name.

src/app/app.component.html (NgModel example)
      
      <label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel">
    

[(ngModel)] 語法只能設定資料繫結屬性。

This [(ngModel)] syntax can only set a data-bound property.

要自訂配置,你可以編寫可展開的表單,該表單將屬性繫結和事件繫結分開。使用屬性繫結來設定屬性,並使用事件繫結來響應更改。以下示例將 <input> 值更改為大寫:

To customize your configuration, you can write the expanded form, which separates the property and event binding. Use property binding to set the property and event binding to respond to changes. The following example changes the <input> value to uppercase:

src/app/app.component.html
      
      <input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase">
    

這裡是所有這些變體的動畫,包括這個大寫轉換的版本:

Here are all variations in action, including the uppercase version:

NgModel 和值訪問器

NgModel and value accessors

NgModel 指令適用於ControlValueAccessor支援的元素。Angular 為所有基本 HTML 表單元素提供了值訪問器。有關更多資訊,請參見Forms

The NgModel directive works for an element supported by a ControlValueAccessor. Angular provides value accessors for all of the basic HTML form elements. For more information, see Forms.

要將 [(ngModel)] 應用於非格式本機元素或第三方自訂元件,必須編寫一個值訪問器。有關更多資訊,請參見DefaultValueAccessor上的 API 文件。

To apply [(ngModel)] to a non-form native element or a third-party custom component, you have to write a value accessor. For more information, see the API documentation on DefaultValueAccessor.

編寫 Angular 元件時,如果根據 Angular 的雙向繫結語法命名 value 和 event 屬性,則不需要用值訪問器(ControlValueAccessor)或 NgModel

When you write an Angular component, you don't need a value accessor or NgModel if you name the value and event properties according to Angular's two-way binding syntax.

內建結構型指令

Built-in structural directives

結構型指令的職責是 HTML 佈局。 它們塑造或重塑 DOM 的結構,這通常是透過新增、移除和操縱它們所附加到的宿主元素來實現的。

Structural directives are responsible for HTML layout. They shape or reshape the DOM's structure, typically by adding, removing, and manipulating the host elements to which they are attached.

本節會介紹最常見的內建結構型指令:

This section introduces the most common built-in structural directives:

  • NgIf—— 從範本中建立或銷燬子檢視。

    NgIf—conditionally creates or disposes of subviews from the template.

  • NgFor—— 為列表中的每個條目重複渲染一個節點。

    NgFor—repeat a node for each item in a list.

  • NgSwitch—— 一組在備用檢視之間切換的指令。

    NgSwitch—a set of directives that switch among alternative views.

要了解更多資訊,參閱結構型指令

For more information, see Structural Directives.

NgIf 新增或刪除元素

Adding or removing an element with NgIf

你可以透過將 NgIf 指令應用於宿主元素來新增或刪除元素。

You can add or remove an element by applying an NgIf directive to a host element.

如果 NgIffalse,則 Angular 將從 DOM 中移除一個元素及其後代。然後,Angular 會銷燬其元件,從而釋放記憶體和資源。

When NgIf is false, Angular removes an element and its descendants from the DOM. Angular then disposes of their components, which frees up memory and resources.

要新增或刪除元素,請在以下示例 *ngIf 繫結到條件表示式,例如 isActive

To add or remove an element, bind *ngIf to a condition expression such as isActive in the following example.

src/app/app.component.html
      
      <app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
    

isActive 表示式返回真值時,NgIf 會把 ItemDetailComponent 新增到 DOM 中。當表示式為假值時,NgIf 會從 DOM 中刪除 ItemDetailComponent 並銷燬該元件及其所有子元件。

When the isActive expression returns a truthy value, NgIf adds the ItemDetailComponent to the DOM. When the expression is falsy, NgIf removes the ItemDetailComponent from the DOM and disposes of the component and all of its sub-components.

關於 NgIfNgIfElse 的更多資訊,請參見NgIf API 文件

For more information on NgIf and NgIfElse, see the NgIf API documentation.

防止 null

Guarding against null

預設情況下,NgIf 會阻止顯示已繫結到空值的元素。

By default, NgIf prevents display of an element bound to a null value.

要使用 NgIf 保護 <div>,請將 *ngIf="yourProperty" 新增到此 <div>。在下面的例子中,currentCustomer 名字出現了,是因為確實存在一個 currentCustomer

To use NgIf to guard a <div>, add *ngIf="yourProperty" to the <div>. In the following example, the currentCustomer name appears because there is a currentCustomer.

src/app/app.component.html
      
      <div *ngIf="currentCustomer">Hello, {{currentCustomer.name}}</div>
    

但是,如果該屬性為 null,則 Angular 就不會顯示 <div>。在這個例子中,Angular 就不會顯示 nullCustomer,因為它為 null

However, if the property is null, Angular does not display the <div>. In this example, Angular does not display the nullCustomer because it is null.

src/app/app.component.html
      
      <div *ngIf="nullCustomer">Hello, <span>{{nullCustomer}}</span></div>
    

NgFor 條目列表

Listing items with NgFor

你可以使用 NgFor 來指令顯示條目列表。

You can use the NgFor directive to present a list of items.

  1. 定義一個 HTML 塊,該塊會決定 Angular 如何渲染單個條目。

    Define a block of HTML that determines how Angular renders a single item.

  2. 要列出你的條目,請把一個簡寫形式 let item of items 賦值給 *ngFor

    To list your items, assign the short hand let item of items to *ngFor.

src/app/app.component.html
      
      <div *ngFor="let item of items">{{item.name}}</div>
    

字串 "let item of items" 會指示 Angular 執行以下操作:

The string "let item of items" instructs Angular to do the following:

  • items 中的每個條目儲存在區域性迴圈變數 item

    Store each item in the items array in the local item looping variable

  • 讓每個條目都可用於每次迭代時的範本 HTML 中

    Make each item available to the templated HTML for each iteration

  • "let item of items" 轉換為環繞宿主元素的 <ng-template>

    Translate "let item of items" into an <ng-template> around the host element

  • 對列表中的每個 item 複寫這個 <ng-template>

    Repeat the <ng-template> for each item in the list

欲知詳情,請參閱結構型指令中的結構型指令的簡寫形式部分。

For more information see the Structural directive shorthand section of Structural directives.

複寫元件檢視

Repeating a component view

要複寫某個元件元素,請將 *ngFor 應用於其選擇器。在以下示例中,選擇器為 <app-item-detail>

To repeat a component element, apply *ngFor to the selector. In the following example, the selector is <app-item-detail>.

src/app/app.component.html
      
      <app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
    

你可以在以下位置參考範本輸入變數,例如 item

You can reference a template input variable, such as item, in the following locations:

  • ngFor 的宿主元素中

    within the ngFor host element

  • 在宿主元素的後代中,用以訪問條目的屬性

    within the host element descendants to access the item's properties

以下示例首先在插值中參考 item,然後將它透過繫結傳遞給 <app-item-detail> 元件的 item 屬性。

The following example references item first in an interpolation and then passes in a binding to the item property of the <app-item-detail> component.

src/app/app.component.html
      
      <div *ngFor="let item of items">{{item.name}}</div>
<!-- . . . -->
  <app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
    

有關範本輸入變數的更多資訊,請參見《結構型指令簡寫形式》](guide/structural-directives#shorthand)。

For more information about template input variables, see Structural directive shorthand.

獲取 *ngForindex

Getting the index of *ngFor

你可以獲取 *ngForindex,並在範本中使用它。

You can get the index of *ngFor in a template input variable and use it in the template.

*ngFor 中,新增一個分號和 let i=index 簡寫形式。下面的例子中把 index 取到一個名為 i 的變數中,並將其與條目名稱一起顯示。

In the *ngFor, add a semicolon and let i=index to the short hand. The following example gets the index in a variable named i and displays it with the item name.

src/app/app.component.html
      
      <div *ngFor="let item of items; let i=index">{{i + 1}} - {{item.name}}</div>
    

NgFor 指令上下文的 index 屬性在每次迭代中都會返回該條目的從零開始的索引號。

The index property of the NgFor directive context returns the zero-based index of the item in each iteration.

Angular 會將此指令轉換為 <ng-template>,然後反覆使用此範本為列表中的每個 item 建立一組新的元素和繫結。有關簡寫形式的更多資訊,請參見《結構型指令》指南。

Angular translates this instruction into an <ng-template> around the host element, then uses this template repeatedly to create a new set of elements and bindings for each item in the list. For more information about shorthand, see the Structural Directives guide.

當條件為真時複寫元素

Repeating elements when a condition is true

要在特定條件為 true 時複寫 HTML 塊,請將 *ngIf 放在 *ngFor 元素的容器元素上。它們之一或兩者都可以是 <ng-container>,這樣你就不必引入額外的 HTML 層次了。

To repeat a block of HTML when a particular condition is true, put the *ngIf on a container element that wraps an *ngFor element. One or both elements can be an <ng-container> so you don't have to introduce extra levels of HTML.

由於結構型指令會在 DOM 中新增和刪除節點,因此每個元素只能應用一個結構型指令。

Because structural directives add and remove nodes from the DOM, apply only one structural directive per element.

有關 NgFor 的更多資訊,請參見NgForOf API 參考

For more information about NgFor see the NgForOf API reference.

*ngFortrackBy 追蹤條目

Tracking items with *ngFor trackBy

透過追蹤對條目列表的更改,可以減少應用程式對伺服器的呼叫次數。使用 *ngFortrackBy 屬性,Angular 只能更改和重新渲染已更改的條目,而不必重新載入整個條目列表。

By tracking changes to an item list, you can reduce the number of calls your application makes to the server. With the *ngFor trackBy property, Angular can change and re-render only those items that have changed, rather than reloading the entire list of items.

  1. 向該元件新增一個方法,該方法返回 NgFor 應該追蹤的值。這個例子中,該值是英雄的 id。如果瀏覽器已經渲染過此 id,Angular 就會追蹤它,而不會重新向伺服器查詢相同的 id

    Add a method to the component that returns the value NgFor should track. In this example, the value to track is the item's id. If the browser has already rendered id, Angular keeps track of it and doesn't re-query the server for the same id.

src/app/app.component.ts
      
      trackByItems(index: number, item: Item): number { return item.id; }
    
  1. 在簡寫表示式中,將 trackBy 設定為 trackByItems() 方法。

    In the short hand expression, set trackBy to the trackByItems() method.

src/app/app.component.html
      
      <div *ngFor="let item of items; trackBy: trackByItems">
  ({{item.id}}) {{item.name}}
</div>
    

更改這些 ID 會使用新的 item.id 建立新的條目。在下面的 trackBy 效果示範中,Reset items 會建立一些具有和以前相同的 item.id 的新條目。

Change ids creates new items with new item.ids. In the following illustration of the trackBy effect, Reset items creates new items with the same item.ids.

  • 如果沒有 trackBy,這些按鈕都會觸發完全的 DOM 元素替換。

    With no trackBy, both buttons trigger complete DOM element replacement.

  • 有了 trackBy,則只有修改了 id 的按鈕才會觸發元素替換。

    With trackBy, only changing the id triggers element replacement.

內建指令僅僅使用了公共 API。它們沒有用到任何其它指令無權訪問的私有 API。

Built-in directives use only public APIs. They do not have special access to any private APIs that other directives can't access.

為沒有 DOM 元素的指令安排宿主

Hosting a directive without a DOM element

Angular 的 <ng-container> 是一個分組元素,它不會干擾樣式或佈局,因為 Angular 不會將其放置在 DOM 中。

The Angular <ng-container> is a grouping element that doesn't interfere with styles or layout because Angular doesn't put it in the DOM.

當沒有單個元素承載指令時,可以使用 <ng-container>

You can use <ng-container> when there's no single element to host the directive.

這是使用 <ng-container> 的條件化段落。

Here's a conditional paragraph using <ng-container>.

src/app/app.component.html (ngif-ngcontainer)
      
      <p>
  I turned the corner
  <ng-container *ngIf="hero">
    and saw {{hero.name}}. I waved
  </ng-container>
  and continued on my way.
</p>
    
  1. FormsModule 中匯入 ngModel 指令。

    Import the ngModel directive from FormsModule.

  2. FormsModule 新增到相關 Angular 模組的 imports 部分。

    Add FormsModule to the imports section of the relevant Angular module.

  3. 要有條件地排除 <option>,請將 <option> 包裹在 <ng-container> 中。

    To conditionally exclude an <option>, wrap the <option> in an <ng-container>.

    src/app/app.component.html (select-ngcontainer)
          
          <div>
      Pick your favorite hero
      (<label><input type="checkbox" checked (change)="showSad = !showSad">show sad</label>)
    </div>
    <select [(ngModel)]="hero">
      <ng-container *ngFor="let h of heroes">
        <ng-container *ngIf="showSad || h.emotion !== 'sad'">
          <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option>
        </ng-container>
      </ng-container>
    </select>
        

NgSwitch

Switching cases with NgSwitch

就像 JavaScript 的 switch 語句一樣。NgSwitch 會根據切換條件顯示幾個可能的元素中的一個。Angular 只會將選定的元素放入 DOM。

Like the JavaScript switch statement, NgSwitch displays one element from among several possible elements, based on a switch condition. Angular puts only the selected element into the DOM.

NgSwitch 是一組指令(共三個):

NgSwitch is a set of three directives:

  • NgSwitch —— 一個屬性型指令,它更改其伴生指令的行為。

    NgSwitch—an attribute directive that changes the behavior of its companion directives.

  • NgSwitchCase —— 結構型指令,當其繫結值等於開關值時將其元素新增到 DOM 中,而在其不等於開關值時將其繫結值移除。

    NgSwitchCase—structural directive that adds its element to the DOM when its bound value equals the switch value and removes its bound value when it doesn't equal the switch value.

  • NgSwitchDefault —— 結構型指令,當沒有選中的 NgSwitchCase 時,將其宿主元素新增到 DOM 中。

    NgSwitchDefault—structural directive that adds its element to the DOM when there is no selected NgSwitchCase.

  1. 在每個元素(比如<div>)上,把 [ngSwitch] 繫結到一個返回開關值的表示式(例如 feature)。儘管這個例子中 feature 值是字串,但此開關值可以是任何型別。

    On an element, such as a <div>, add [ngSwitch] bound to an expression that returns the switch value, such as feature. Though the feature value in this example is a string, the switch value can be of any type.

  2. 將各個分支元素繫結到 *ngSwitchCase*ngSwitchDefault

    Bind to *ngSwitchCase and *ngSwitchDefault on the elements for the cases.

    src/app/app.component.html
          
          <div [ngSwitch]="currentItem.feature">
      <app-stout-item    *ngSwitchCase="'stout'"    [item]="currentItem"></app-stout-item>
      <app-device-item   *ngSwitchCase="'slim'"     [item]="currentItem"></app-device-item>
      <app-lost-item     *ngSwitchCase="'vintage'"  [item]="currentItem"></app-lost-item>
      <app-best-item     *ngSwitchCase="'bright'"   [item]="currentItem"></app-best-item>
    <!-- . . . -->
      <app-unknown-item  *ngSwitchDefault           [item]="currentItem"></app-unknown-item>
    </div>
        
  3. 在父元件中,定義 currentItem 以便可以在 [ngSwitch] 表示式中使用它。

    In the parent component, define currentItem so you can use it in the [ngSwitch] expression.

    src/app/app.component.ts
          
          currentItem!: Item;
        
  4. 在每個子元件中,新增一個輸入屬性 item,該屬性會繫結到父元件的 currentItem。以下兩個片段顯示了父元件和其中一個子元件。其他子元件與 StoutItemComponent 中的相同。

    In each child component, add an item input property which is bound to the currentItem of the parent component. The following two snippets show the parent component and one of the child components. The other child components are identical to StoutItemComponent.

    In each child component, here StoutItemComponent
          
          export class StoutItemComponent {
      @Input() item!: Item;
    }
        

Switch 指令也同樣適用於原生 HTML 元素和 Web Component。 比如,你可以像下面的例子中一樣把 <app-best-item> 分支替換為 <div>

Switch directives also work with native HTML elements and web components. For example, you could replace the <app-best-item> switch case with a <div> as follows.

src/app/app.component.html
      
      <div *ngSwitchCase="'bright'"> Are you as bright as {{currentItem.name}}?</div>
    

接下來呢?

What's next

有關如何建構自己的自訂指令的資訊,請參見“屬性型指令”“結構型指令”

For information on how to build your own custom directives, see Attribute Directives and Structural Directives.