Angular中的內建指令
Angular提供了若干內建指令。因為內建指令是已經匯入過的,故可以直接在元件中直接使用它們。
ngIf
如果你希望根據一個條件來決定顯示或隱藏一個元素,可以使用ngIf指令。這個條件是由你傳給指令的表示式的結果決定的。
如果表示式的結果返回的是一個假值,那麼元素會從DOM上被移除。
下面是一些例子:
div *ngIf="false"></div> <!--nerver displayed--> <div *ngIf="a>b"></div> <!--displayed if a is more than b--> <div *ngIf="str == 'yes'"></div> <!--displayed if str holds the string "yes" --> <div *ngIf="myFunc()"></div> <!--displayed if myFunc returns a true value -->
ngSwitch
有時候你需要根據一個給定的條件來渲染不同的元素。
遇到這種情況時,你可能會像下面這樣多次使用ngIf:
<div class="container"> <div *ngIf="myVar=='A'">Var is A</div> <div *ngIf="myVar=='B'">Var is B</div> <div *ngIf="myVar!='A' && myVar!='B'">Var is something else</div> </div>
如你所見,當myVar的值既不是A也不是B時,程式碼變得相當繁瑣,其實我們真正想表達的只是一個else而已。隨著我們新增的值越來越多,ngIf條件也會變得越來越繁瑣。對於這種情況,Angular引入了ngSwicth指令。
ngSwitch對錶達式進行一次求值,然後根據其結果來決定如何顯示指令內的巢狀元素。
一旦有了結果,我們就可以:
1、使用ngSwitchCase指令描述已知結果
2、使用ngSwitchDefault指令處理所有其他未知情況。
讓我們使用這組新的指令來重寫之前的例子
<div class="container" [ngSwitch]="myVar"> <div *ngSwitchCase="'A'">Var is A</div> <div *ngSwitchCase="'B'">Var is B</div> <div *ngSwitchDefault>Var is something else</div> </div>
使用此指令擴充套件很方便,如果想處理新值C,只需要插入一行:
<div class="container" [ngSwitch]="myVar">
<div *ngSwitchCase="'A'">Var is A</div>
<div *ngSwitchCase="'B'">Var is B</div>
<div *ngSwitchCase="'C'">Var is C</div>
<div *ngSwitchDefault>Var is something else</div>
</div>
ngSwitchDefault元素是可選的。如果我們不用它,那麼當myVar沒有匹配到任何期望的值時就不會渲染任何東西。
你也可以為不同的元素宣告同樣的*ngSwitchCase值,這樣就可以多次匹配同一個值了,例子如下:
template:`
<h4 class="ui horizontal divider header">
Current choice is {{ choice }}
</h4>
<div class="ui raised segment">
<ul [ngSwitch]="choice">
<li *ngSwitchCase="1">First choice</li>
<li *ngSwitchCase="2">Second choice</li>
<li *ngSwitchCase="3">Third choice</li>
<li *ngSwitchCase="4">Fourth choice</li>
<li *ngSwitchCase="2">Second choice, again</li>
<li *ngSwitchDefault>Default choice</li>
</ul>
</div>
<div style="margin-top: 20px;">
<button class="ui primary button" (click)="nextChoice()">
Next choice
</button>
</div>
`
在上面的例子中,當choice的值是2的時候,第2個和第5個li都會被渲染。
ngStyle
使用ngStyle指令,可以通過Angular表示式給特定的DOM元素設定CSS屬性。
該指令最簡單的用法就是[style.<cssproperty>]=”value”的形式,下面是一個例子:
<div [style.background-color]="'yellow'">
Uses fixed yellow background
</div>
這個程式碼片段就是使用ngStyle指令把css的background-color屬性設定為字面量yellow。
另一種設定固定值的方式就是使用ngStyle屬性,使用鍵值對來設定每個屬性。
<div [ngStyle]="{color: 'white', 'background-color': 'blue'}">
Uses fixed white text on blue background
</div>
此處說明一下:在ngStyle的說明中,我們對background-color使用了單引號,但卻沒有對color使用,因為ngStyle的引數是一個JavaScript物件,而color是一個合法的鍵,不需要引號,但是在background-color中,連字元是不允許出現在物件的鍵名當中的,除非它是一個字串,因此使用了引號。通常情況下,儘量不要對物件的鍵使用引號,除非不得不用。
我們在這裡同時設定了color和background-color屬性。
但ngStyle指令真正的能力在於使用動態值。
在這個例子中,我們定義了兩個輸入框。
<div class="ui input">
<input type="text" name="color" value="{{color}}" #colorinput>
</div>
<div class="ui input">
<input type="text" name="fontSize" value="{{fontSize}}" #fontinput>
</div>
<button class="ui primary button" (click)="apply(colorinput.value, fontinput.value)">
Apply settings
</button>
然後使用它們的值來設定三個元素的CSS屬性。
在第一個元素中,我們基於輸入框的值來設定字型大小。
<div>
<span [ngStyle]="{color: 'red'}" [style.font-size.px]="fontSize">
red text
</span>
</div>
注意,我們在某些情況下必須指定單位。例如,把font-size設定為12不是合法的CSS,必須指定一個單位,比如12px或者1.2em。Angular提供了一個便捷語法用來指定單位:這裡我們使用的格式是[style.font-size.px]。
字尾.px表明我們設定font-size屬性值以畫素為單位。你完全可以把它替換為[style.font-size.em],以相對長度為單位來表示字型大小,還可以使用[style.font-size.%],以百分比為單位。
另外兩個元素使用#colorinput的值來設定文字顏色和背景顏色。
<h4 class="ui horizontal divider header">
ngStyle with object property from variable
</h4>
<div>
<span [ngStyle]="{color: color}">
{{ color }} text
</span>
</div>
<h4 class="ui horizontal divider header">
style from variable
</h4>
<div [style.background-color]="color"
style="color: white;">
{{ color }} background
</div>
這樣,當我們點選Apply settings按鈕時,就會呼叫方法來設定新的值。
apply(color: string, fontSize: number) {
this.color = color;
this.fontSize = fontSize;
}
與此同時,文字顏色和字型大小都通過NgStyle指令作用在元素上。
ngClass
ngClass指令在HTML模板中用ngClass屬性來表示,讓你能動態設定和改變一個給定DOM元素的CSS類。
使用這個指令的第一種方式是傳入一個物件字面量。該物件希望以類名作為鍵,而值應該是一個用來表明是否應該應用該類的真假值。
假設我們有一個叫作bordered的CSS類,用來給元素新增一個黑色虛線邊框。
.bordered {
border: 1px dashed black;
background-color: #eee;
}
我們來新增兩個div元素,一個一直都有bordered類,而另一個永遠都不會有。
div [ngClass]="{bordered: false}">This is never bordered</div>
<div [ngClass]="{bordered: true}">This is always bordered</div>
如預期一樣,兩個div應該是下圖這樣渲染的。
當然,使用ngClass指令來動態分配樣式類會用的更多。
為了動態使用它,我們新增一個變數作為物件的值:
<div [ngClass]="{bordered: isBordered}">
Using object literal. Border {{ isBordered ? "ON" : "OFF" }}
</div>
或者在元件中定義該物件:
export class NgClassSampleApp{
isBordered: boolean;
classesObj: Object;
並直接使用它:
div [ngClass]="classesObj">
Using object var. Border {{ classesObj.bordered ? "ON" : "OFF" }}
</div>
我們也可以使用一個類名列表來指定哪些類名會被新增到元素上,為此,我們可以傳入一個數組型字面量:
<div class="base" [ngClass]="['blue', 'round']">
This will always have a blue background and
round corners
</div>
或者在元件中宣告一個數組物件:
this.classList = ['blue', 'round'];
並把它傳進來:
<div class="base" [ngClass]="classList">
This is {{ classList.indexOf('blue') > -1 ? "" : "NOT" }} blue
and {{ classList.indexOf('round') > -1 ? "" : "NOT" }} round
</div>
在上面的例子中,[ngClass]分配的類名和通過HTML的class屬性分配的已存在類名都是生效的。
最後新增到元素的類總會是HTML屬性class中的類和[ngClass]指令求值結果得到的類的集合。
ngFor
這個指令的任務是重複一個給定的DOM元素(或一組DOM元素),每次重複都會從陣列中取一個不同的值。
它的語法是*ngFor=”let item of items”。
1)let item語法指定一個用來接收items陣列中每個元素的變數。
2)items是來自元件控制器的一個集合。
要闡明這一點,我們來看一下程式碼示例。我們在元件控制器中聲明瞭一個城市的陣列:
this.cities = ['Miami', 'Sao Paulo', 'New York'];
然後在模板中有如下的HTML片段。
h4 class="ui horizontal divider header">
Simple list of strings
</h4>
<div class="ui list" *ngFor="let c of cities">
<div class="item">{{ c }}</div>
</div>
它會如你期望的那樣在div中渲染每一個城市,如下圖:
我們還可以這樣迭代一個物件陣列。
this.people = [
{ name: 'Anderson', age: 35, city: 'Sao Paulo' },
{ name: 'John', age: 12, city: 'Miami' },
{ name: 'Peter', age: 22, city: 'New York' }
];
然後根據每一行資料渲染出一個表格。
h4 class="ui horizontal divider header">
List of objects
</h4>
<table class="ui celled table">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>City</th>
</tr>
</thead>
<tr *ngFor="let p of people">
<td>{{ p.name }}</td>
<td>{{ p.age }}</td>
<td>{{ p.city }}</td>
</tr>
</table>
結果如下:
我們還可以使用巢狀陣列,如果想根據城市進行分組,可以定義一個新物件陣列。
this.peopleByCity = [
{
city: 'Miami',
people: [
{ name: 'John', age: 12 },
{ name: 'Angel', age: 22 }
]
},
{
city: 'Sao Paulo',
people: [
{ name: 'Anderson', age: 35 },
{ name: 'Felipe', age: 36 }
]
}
];
模板程式碼如下:
<h4 class="ui horizontal divider header">
Nested data
</h4>
<div *ngFor="let item of peopleByCity">
<h2 class="ui header">{{ item.city }}</h2>
<table class="ui celled table">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thead>
<tr *ngFor="let p of item.people">
<td>{{ p.name }}</td>
<td>{{ p.age }}</td>
</tr>
</table>
</div>
它為每個城市渲染一個表格,如下圖:
獲取索引
在迭代陣列時,我們可能也要獲取每一項的索引。
我們可以在ngFor指令的值中插入語法let idx = index並用分號分隔開,這樣就可以獲取索引了。這時候,Angular會把當前的索引分配給我們的變數。
對我們第一個例子稍加改動,新增程式碼段let num = index。
<div class="ui list" *ngFor="let c of cities; let num = index">
<div class="item">{{ num+1 }} - {{ c }}</div>
</div>
它會在城市的名稱前面加上序號,如下圖:
ngNonBindable
當我們想告訴Angular不要編譯或者繫結頁面中的某個特殊部分時,要使用ngNonBindable指令。
假如我們想在模板中渲染純文字{{ content }},通常情況下,這段文字會被繫結到變數content的值,因為我們使用了{{}}模板語法。
那該如何渲染出純文字{{ content }}呢?可以使用ngNonBindable指令。
假如我們想要用一個div來與渲染變數content的內容,緊接著輸出文字<- this is what {{ content }} rendered來指向變數實際的值。
為了做到這一點,要使用下面的模板:
template:`
<div class='ngNonBindableDemo'>
<span class="bordered">{{ content }}</span>
<span class="pre" ngNonBindable>
← This is what {{ content }} rendered
</span>
</div>
`
有了ngNonBindable屬性,Angular不會編譯第二個span裡的內容,而是原封不動地將其顯示出來。
總結
Angular的核心指令數量很少,但我們卻能通過組合這些簡單的指令來建立五花八門的應用。
關於本文中的示例程式碼已託管到github上: