內建指令
Built-in directives
Angular offers two kinds of built-in directives: attribute directives and structural directives.
要檢視包含本指南中程式碼的可工作範例,請參閱
See the
欲知詳情,包括如何建構你自己的自訂指令,請參閱屬性型指令和結構型指令。
For more detail, including how to build your own custom directives, see Attribute Directives and Structural Directives.
內建屬性型指令
Built-in attribute directives
屬性型指令會監聽並修改其它 HTML 元素和元件的行為、Attribute 和 Property。 它們通常被應用在元素上,就好像它們是 HTML 屬性一樣,因此得名屬性型指令。
Attribute directives listen to and modify the behavior of other HTML elements, attributes, properties, and components. You usually apply them to elements as if they were HTML attributes, hence the name.
許多 NgModule(例如 RouterModule
和 FormsModule
都定義了自己的屬性型指令。最常見的屬性型指令如下:
Many NgModules such as the RouterModule
and the FormsModule
define 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
用 ngClass
同時新增或刪除幾個 CSS 類別。
Add or remove several CSS classes simultaneously with ngClass
.
<!-- toggle the "special" class on/off with a property -->
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
要新增或刪除單個類別,請使用類別繫結而不是 NgClass
。
To add or remove a single class, use class binding rather than NgClass
.
考慮一個 setCurrentClasses()
元件方法,該方法設定一個元件屬性 currentClasses
,該物件具有一個根據其它三個元件屬性的 true
/ false
狀態來新增或刪除三個 CSS 類別的物件。該物件的每個鍵(key)都是一個 CSS 類別名稱。如果要新增上該類別,則其值為 true
,反之則為 false
。
Consider a setCurrentClasses()
component method that sets a component property, currentClasses
, with an object that adds or removes three classes based on the true
/false
state of three other component properties. Each key of the object is a CSS class name; its value is true
if the class should be added, false
if it should be removed.
currentClasses: {};
/* . . . */
setCurrentClasses() {
// CSS classes: added/removed per current state of component properties
this.currentClasses = {
saveable: this.canSave,
modified: !this.isUnchanged,
special: this.isSpecial
};
}
把 NgClass
屬性繫結到 currentClasses
,根據它來設定此元素的 CSS 類別:
Adding an ngClass
property binding to currentClasses
sets the element's classes accordingly:
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
請記住,在這種情況下,你要在初始化時和它依賴的屬性發生變化時呼叫 setCurrentClasses()
。
Remember that in this situation you'd call setCurrentClasses()
, both initially and when the dependent properties change.
NgStyle
使用 NgStyle
根據元件的狀態同時動態設定多個內聯樣式。
Use NgStyle
to set many inline styles simultaneously and dynamically, based on the state of the component.
不用 NgStyle
Without NgStyle
有些情況下,要考慮使用樣式繫結來設定單個樣式值,而不使用 NgStyle
。
For context, consider setting a single style value with style binding, without NgStyle
.
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">
This div is x-large or smaller.
</div>
但是,如果要同時設定多個內聯樣式,請使用 NgStyle
指令。
However, to set many inline styles at the same time, use the NgStyle
directive.
下面的例子是一個 setCurrentStyles()
方法,它基於該元件另外三個屬性的狀態,用一個定義了三個樣式的物件設定了 currentStyles
屬性。
The following is a setCurrentStyles()
method that sets a component property, currentStyles
, with an object that defines three styles, based on the state of three other component properties:
currentStyles: {};
/* . . . */
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'
};
}
把 ngStyle
屬性繫結到 currentStyles
,來根據它設定此元素的樣式:
Adding an ngStyle
property binding to currentStyles
sets the element's styles accordingly:
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
請記住,無論是在初始時還是其依賴的屬性發生變化時,都要呼叫 setCurrentStyles()
。
Remember to call setCurrentStyles()
, both initially and when the dependent properties change.
[(ngModel)]
:雙向繫結
[(ngModel)]
: Two-way binding
NgModel
指令允許你顯示資料屬性並在使用者進行更改時更新該屬性。這是一個例子:
The NgModel
directive allows you to display a data property and update that property when the user makes changes. Here's an example:
<label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel">
匯入 FormsModule
以使用 ngModel
Import FormsModule
to use ngModel
要想在雙向資料繫結中使用 ngModel
指令,必須先匯入 FormsModule
並將其新增到 NgModule 的 imports
列表中。要了解關於 FormsModule
和 ngModel
的更多資訊,參閱表單一章。
Before using the ngModel
directive in a two-way data binding, you must import the FormsModule
and add it to the NgModule's imports
list. Learn more about the FormsModule
and ngModel
in Forms.
記住,要匯入 FormsModule
才能讓 [(ngModel)]
可用,如下所示:
Remember to import the FormsModule
to make [(ngModel)]
available as follows:
import { FormsModule } from '@angular/forms'; // <--- JavaScript import from Angular
/* . . . */
@NgModule({
/* . . . */
imports: [
BrowserModule,
FormsModule // <--- import into the NgModule
],
/* . . . */
})
export class AppModule { }
透過分別繫結到 <input>
元素的 value
屬性和 input
事件,可以達到同樣的效果:
You could achieve the same result with separate bindings to the <input>
element's value
property and input
event:
<label for="without">without NgModel:</label>
<input [value]="currentItem.name" (input)="currentItem.name=$event.target.value" id="without">
為了簡化語法,ngModel
指令把技術細節隱藏在其輸入屬性 ngModel
和輸出屬性 ngModelChange
的後面:
To streamline the syntax, the ngModel
directive hides the details behind its own ngModel
input and ngModelChange
output properties:
<label for="example-change">(ngModelChange)="...name=$event":</label>
<input [ngModel]="currentItem.name" (ngModelChange)="currentItem.name=$event" id="example-change">
ngModel
輸入屬性會設定該元素的值,並透過 ngModelChange
的輸出屬性來監聽元素值的變化。
The ngModel
data property sets the element's value property and the ngModelChange
event property listens for changes to the element's value.
NgModel
和值訪問器
NgModel
and value accessors
這些技術細節是針對每種具體元素的,因此 NgModel
指令僅適用於透過 ControlValueAccessor 適配過這種協議的元素。Angular 已經為所有基本的 HTML 表單元素提供了值訪問器,表單一章示範瞭如何繫結到它們。
The details are specific to each kind of element and therefore the NgModel
directive only works for an element supported by a ControlValueAccessor that adapts an element to this protocol. Angular provides value accessors for all of the basic HTML form elements and the Forms guide shows how to bind to them.
在編寫適當的值訪問器之前,不能將 [(ngModel)]
應用於非表單的原生元素或第三方自訂元件。欲知詳情,參閱DefaultValueAccessor上的 API 文件。
You can't apply [(ngModel)]
to a non-form native element or a third-party custom component until you write a suitable value accessor. For more information, see the API documentation on DefaultValueAccessor.
你不一定非用為所編寫的 Angular 元件提供值訪問器,因為你還可以把值屬性和事件屬性命名為符合 Angular 的基本雙向繫結語法的形式,並完全跳過 NgModel
。雙向繫結部分的 sizer
是此技術的一個範例。
You don't need a value accessor for an Angular component that you write because you can name the value and event properties to suit Angular's basic two-way binding syntax and skip NgModel
altogether. The sizer
in the Two-way Binding section is an example of this technique.
單獨的 ngModel
繫結是對繫結到元素的原生屬性方式的一種改進,但你可以使用 [(ngModel)]
語法來透過單個宣告簡化繫結:
Separate ngModel
bindings are an improvement over binding to the element's native properties, but you can streamline the binding with a single declaration using the [(ngModel)]
syntax:
<label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel">
此 [(ngModel)]
語法只能設定資料繫結屬性。如果你要做得更多,可以編寫擴充套件表單。例如,下面的程式碼將 <input>
值更改為大寫:
This [(ngModel)]
syntax can only set a data-bound property. If you need to do something more, you can write the expanded form; for example, the following changes the <input>
value to uppercase:
<input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase">
這裡是所有這些變體的動畫,包括這個大寫轉換的版本:
Here are all variations in action, including the uppercase version:

內建結構型指令
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 is an introduction to the common built-in structural directives:
NgIf
—— 從範本中建立或銷燬子檢視。NgIf
—conditionally creates or destroys 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.
結構型指令一章涵蓋了結構型指令的詳細內容,它解釋了以下內容:
The deep details of structural directives are covered in the Structural Directives guide, which explains the following:
為什麼在要指令名稱前加上星號(*)。
當指令沒有合適的宿主元素時,使用
<ng-container>
對元素進行分組。Using
<ng-container>
to group elements when there is no suitable host element for the directive.如何寫自己的結構型指令。
How to write your own structural directive.
為什麼你只能往一個元素上應用一個結構型指令。
Why you can only apply one structural directive to an element.
NgIf
你可以透過將 NgIf
指令應用在宿主元素上來從 DOM 中新增或刪除元素。在此範例中,將指令繫結到了條件表示式,例如 isActive
。
You can add or remove an element from the DOM by applying an NgIf
directive to a host element. Bind the directive to a condition expression like isActive
in this example.
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
不要忘了 ngIf
前面的星號(*
)。關於星號的更多資訊,請參閱 結構型指令中的星號(*)字首部分。
Don't forget the asterisk (*
) in front of ngIf
. For more information on the asterisk, see the asterisk (*) prefix section of Structural Directives.
當 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, destroying that component and all of its sub-components.
顯示/隱藏與 NgIf
Show/hide vs. NgIf
隱藏元素與使用 NgIf
刪除元素不同。為了進行比較,下面的範例示範如何使用類別或樣式繫結來控制元素的可見性。
Hiding an element is different from removing it with NgIf
. For comparison, the following example shows how to control the visibility of an element with a class or style binding.
<!-- isSpecial is true -->
<div [class.hidden]="!isSpecial">Show with class</div>
<div [class.hidden]="isSpecial">Hide with class</div>
<p>ItemDetail is in the DOM but hidden</p>
<app-item-detail [class.hidden]="isSpecial"></app-item-detail>
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
隱藏元素時,該元素及其所有後代仍保留在 DOM 中。這些元素的所有元件都保留在記憶體中,Angular 會繼續做變更檢查。它可能會佔用大量計算資源,並且會不必要地降低效能。
When you hide an element, that element and all of its descendants remain in the DOM. All components for those elements stay in memory and Angular may continue to check for changes. You could be holding onto considerable computing resources and degrading performance unnecessarily.
NgIf
工作方式有所不同。如果 NgIf
為 false
,則 Angular 將從 DOM 中刪除該元素及其後代。這銷燬了它們的元件,釋放了資源,從而帶來更好的使用者體驗。
NgIf
works differently. When NgIf
is false
, Angular removes the element and its descendants from the DOM. It destroys their components, freeing up resources, which results in a better user experience.
如果要隱藏大型元件樹,請考慮使用 NgIf
作為顯示/隱藏的更有效替代方法。
If you are hiding large component trees, consider NgIf
as a more efficient alternative to showing/hiding.
關於 NgIf
和 ngIfElse
的更多資訊,請參閱 關於 NgIf 的 API 文件。
For more information on NgIf
and ngIfElse
, see the API documentation about NgIf.
防範空指標錯誤
Guard against null
ngIf
另一個優點是你可以使用它來防範空指標錯誤。顯示/隱藏就是最合適的極簡用例,當你需要防範時,請改用 ngIf
代替。如果其中巢狀的表示式嘗試訪問 null
的屬性,Angular 將引發錯誤。
Another advantage of ngIf
is that you can use it to guard against null. Show/hide is best suited for very simple use cases, so when you need a guard, opt instead for ngIf
. Angular will throw an error if a nested expression tries to access a property of null
.
下面的例子中 NgIf
保護著兩個 <div>
。僅當存在 currentCustomer
時,才會顯示 currentCustomer
名稱。除非它為 null
否則不會顯示 nullCustomer
。
The following shows NgIf
guarding two <div>
s. The currentCustomer
name appears only when there is a currentCustomer
. The nullCustomer
will not be displayed as long as it is null
.
<div *ngIf="currentCustomer">Hello, {{currentCustomer.name}}</div>
<div *ngIf="nullCustomer">Hello, <span>{{nullCustomer}}</span></div>
NgFor
NgFor
是一個重複器指令 —— 一種用來顯示條目列表的方法。你定義了一個 HTML 塊,該 HTML 塊定義了應如何顯示單個條目,然後告訴 Angular 以該塊為範本來渲染列表中的每個條目。賦值給 *ngFor
的文字是用來指導重複器工作過程的指令。
NgFor
is a repeater directive—a way to present a list of items. You define a block of HTML that defines how a single item should be displayed and then you tell Angular to use that block as a template for rendering each item in the list. The text assigned to *ngFor
is the instruction that guides the repeater process.
以下範例顯示瞭如何將 NgFor
應用於簡單的 <div>
。
The following example shows NgFor
applied to a simple <div>
.
<div *ngFor="let item of items">{{item.name}}</div>
不要忘了 ngFor
前面的星號(*
)。關於星號的更多資訊,請參閱結構型指令中的星號(*)字首部分。
Don't forget the asterisk (*
) in front of ngFor
. For more information on the asterisk, see the asterisk (*) prefix section of Structural Directives.
你還可以將 NgFor
應用於元件元素,如以下範例所示。
You can also apply an NgFor
to a component element, as in the following example.
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
賦值給 *ngFor
的字串不是範本表示式。而是一個微語法 —— 由 Angular 解釋的一種小型語言。字串 "let item of items"
的意思是:
The string assigned to *ngFor
is not a template expression. Rather, it's a microsyntax—a little language of its own that Angular interprets. The string "let item of items"
means:
將
items
陣列中的每個條目儲存在區域性迴圈變數item
中,並使其可用於每次迭代的範本 HTML 中。Take each item in the
items
array, store it in the localitem
looping variable, and make it available to the templated HTML for 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 microsyntax, see the Structural Directives guide.
範本輸入變數
Template input variables
item
前面的 let
關鍵字建立了一個名為 item
的範本輸入變數。ngFor
指令迭代父元件的 items
屬性所返回的 items
陣列,並在每次迭代期間將 item
設定為該陣列中的當前條目。
The let
keyword before item
creates a template input variable called item
. The ngFor
directive iterates over the items
array returned by the parent component's items
property and sets item
to the current item from the array during each iteration.
ngFor
的宿主元素及其後代中可參考 item
,來訪問該條目的屬性。以下範例首先在插值中參考 item
,然後把一個繫結表示式傳入 <app-item-detail>
元件的 item
屬性。
Reference item
within the ngFor
host element as well as within its descendants to access the item's properties. 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.
<div *ngFor="let item of items">{{item.name}}</div>
<!-- . . . -->
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
關於範本輸入變數的更多資訊,請參閱結構型指令。
For more information about template input variables, see Structural Directives.
*ngFor
與 index
*ngFor
with index
NgFor
指令上下文中的 index
屬性在每次迭代中返回該條目的從零開始的索引。 你可以在範本輸入變數中捕獲 index
,並在範本中使用它。
The index
property of the NgFor
directive context returns the zero-based index of the item in each iteration. You can capture the index
in a template input variable and use it in the template.
下面的例子在名為 i
的變數中捕獲 index
,並將其與條目名稱一起顯示。
The next example captures the index
in a variable named i
and displays it with the item name.
<div *ngFor="let item of items; let i=index">{{i + 1}} - {{item.name}}</div>
要學習更多的類似 index 的值,例如 last
、even
和 odd
,請參閱 NgFor API 參考。
NgFor
is implemented by the NgForOf
directive. Read more about the other NgForOf
context values such as last
, even
, and odd
in the NgForOf API reference.
帶 trackBy
的 *ngFor
*ngFor with trackBy
如果將 NgFor
與大型列表一起使用,則對某個條目的較小更改(例如刪除或新增一項)就會觸發一系列 DOM 操作。 例如,重新查詢伺服器可能會重置包含所有新條目物件的列表,即使先前已顯示這些條目也是如此。在這種情況下,Angular 只能看到由新的物件參考組成的新列表,它別無選擇,只能用所有新的 DOM 元素替換舊的 DOM 元素。
If you use NgFor
with large lists, a small change to one item, such as removing or adding an item, can trigger a cascade of DOM manipulations. For example, re-querying the server could reset a list with all new item objects, even when those items were previously displayed. In this case, Angular sees only a fresh list of new object references and has no choice but to replace the old DOM elements with all new DOM elements.
你可以使用 trackBy
來讓它更加高效。向該元件新增一個方法,該方法返回 NgFor
應該追蹤的值。這個例子中,該值是英雄的 id
。如果 id
已經被渲染,Angular 就會追蹤它,而不會重新向伺服器查詢相同的 id
。
You can make this more efficient with trackBy
. Add a method to the component that returns the value NgFor
should track. In this case, that value is the hero's id
. If the id
has already been rendered, Angular keeps track of it and doesn't re-query the server for the same id
.
trackByItems(index: number, item: Item): number { return item.id; }
在微語法表示式中,將 trackBy
設定為 trackByItems()
方法。
In the microsyntax expression, set trackBy
to the trackByItems()
method.
<div *ngFor="let item of items; trackBy: trackByItems">
({{item.id}}) {{item.name}}
</div>
這就是 trackBy
效果的說明。“Reset items” 將建立具有相同 item.id
的新條目。“Change ids” 將使用新的 item.id
建立新條目。
Here is an illustration of the trackBy
effect. "Reset items" creates new items with the same item.id
s. "Change ids" creates new items with new item.id
s.
如果沒有
trackBy
,這些按鈕都會觸發完全的 DOM 元素替換。With no
trackBy
, both buttons trigger complete DOM element replacement.有了
trackBy
,則只有修改了id
的按鈕才會觸發元素替換。With
trackBy
, only changing theid
triggers element replacement.

內建指令僅僅使用了公共 API。也就是說,它們沒有用到任何其它指令無權訪問的私有 API。
Built-in directives use only public APIs; that is, they do not have special access to any private APIs that other directives can't access.
NgSwitch
指令
The NgSwitch
directives
NgSwitch 類似於 JavaScript switch
語句。它根據切換條件顯示幾個可能的元素中的一個。Angular 只會將選定的元素放入 DOM。
NgSwitch is like the JavaScript switch
statement. It displays one element from among several possible elements, based on a switch condition. Angular puts only the selected element into the DOM.
NgSwitch
實際上是三個協作指令的集合: NgSwitch
,NgSwitchCase
和 NgSwitchDefault
,如以下範例所示。
NgSwitch
is actually a set of three, cooperating directives: NgSwitch
, NgSwitchCase
, and NgSwitchDefault
as in the following example.
<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>

NgSwitch
是控制器指令。把它繫結到一個返回開關值的表示式,例如 feature
。儘管此範例中的 feature
值是字串,但開關值可以是任何型別。
NgSwitch
is the controller directive. Bind it 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.
繫結到 [ngSwitch]
。如果試圖寫成 *ngSwitch
,就會出現錯誤,因為 NgSwitch
是屬性型指令,而不是結構型指令。它不會直接接觸 DOM,而是會更改與之相伴的指令的行為。
Bind to [ngSwitch]
. You'll get an error if you try to set *ngSwitch
because NgSwitch
is an attribute directive, not a structural directive. Rather than touching the DOM directly, it changes the behavior of its companion directives.
繫結到 *ngSwitchCase
和 *ngSwitchDefault
NgSwitchCase
和 NgSwitchDefault
指令都是結構型指令,因為它們會從 DOM 中新增或移除元素。
Bind to *ngSwitchCase
and *ngSwitchDefault
. The NgSwitchCase
and NgSwitchDefault
directives are structural directives because they add or remove elements from the DOM.
當
NgSwitchCase
的繫結值等於開關值時,就將其元素新增到 DOM 中;否則從 DOM 中刪除。NgSwitchCase
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
adds its element to the DOM when there is no selectedNgSwitchCase
.
開關指令對於新增和刪除元件元素特別有用。本範例在 item-switch.components.ts
檔案中定義的四個 item
元件之間切換。每個元件都有一個名叫 item
的輸入屬性,它會繫結到父元件的 currentItem
。
The switch directives are particularly useful for adding and removing component elements. This example switches among four item
components defined in the item-switch.components.ts
file. Each component has an item
input property which is bound to the currentItem
of the parent component.
開關指令也同樣適用於原生元素和 Web Component。 比如,你可以把 <app-best-item>
分支替換為如下程式碼。
Switch directives work as well with native elements and web components too. For example, you could replace the <app-best-item>
switch case with the following.
<div *ngSwitchCase="'bright'"> Are you as bright as {{currentItem.name}}?</div>