1. 程式人生 > >Angular中的內建指令

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個和第5li都會被渲染。

ngStyle

使用ngStyle指令,可以通過Angular表示式給特定的DOM元素設定CSS屬性。

該指令最簡單的用法就是[style.<cssproperty>]=”value”的形式,下面是一個例子:

<div [style.background-color]="'yellow'">
  Uses fixed yellow background
</div>

這個程式碼片段就是使用ngStyle指令把cssbackground-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中,連字元是不允許出現在物件的鍵名當中的,除非它是一個字串,因此使用了引號。通常情況下,儘量不要對物件的鍵使用引號,除非不得不用。

我們在這裡同時設定了colorbackground-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.2emAngular提供了一個便捷語法用來指定單位:這裡我們使用的格式是[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類。

使用這個指令的第一種方式是傳入一個物件字面量。該物件希望以類名作為鍵,而值應該是一個用來表明是否應該應用該類的真假值。

假設我們有一個叫作borderedCSS類,用來給元素新增一個黑色虛線邊框。

.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]分配的類名和通過HTMLclass屬性分配的已存在類名都是生效的。

最後新增到元素的類總會是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>
      &larr; This is what {{ content }} rendered
    </span>
  </div>
`

有了ngNonBindable屬性,Angular不會編譯第二個span裡的內容,而是原封不動地將其顯示出來。

總結

Angular的核心指令數量很少,但我們卻能通過組合這些簡單的指令來建立五花八門的應用。

關於本文中的示例程式碼已託管到github上: