一直想寫關於 Angular 1.x 與 Angular 2.x (Angular 4.x 已發佈) 區別的文章,方便 Angular 1.x 的用戶快速的過渡到 Angular 2.x。在瀏覽文章的時候,發現 Todd Motto 大神,已經寫了相關的系列文章。英文好的同窗,建議直接閱讀 From ng-repeat in Angular 1.x to ngFor in Angular 2 原文哈,由於我並不打算完整地翻譯。廢話很少說,接下來咱們開始進入正題。javascript
Angular 1.xhtml
Using ng-repeatjava
Using $index and track byangularjs
Angular 2.xweb
Using ngFortypescript
Using index and trackBysegmentfault
在使用 ng-repeat
指令以前,咱們須要組件相關的控制器中設置添加初始數據,具體以下:api
const app = { controller() { this.groceries = [{ id: 0, label: 'Butter' },{ id: 1, label: 'Apples' },{ id: 2, label: 'Paprika' },{ id: 3, label: 'Potatoes' },{ id: 4, label: 'Oatmeal' },{ id: 5, label: 'Spaghetti' },{ id: 6, label: 'Pears' },{ id: 7, label: 'Bacon' }]; } }; angular .module('app') .component('app', app);
接下來咱們在組件模板中,使用 ng-repeat
指令顯示咱們上面定義的數據:數組
const app = { template: ` <div> Grocery selected: {{ $ctrl.selectedGrocery.label }} <ul> <li ng-repeat="grocery in $ctrl.groceries"> <a href="" ng-click="$ctrl.selectGrocery(grocery);"> {{ grocery.label }} </a> </li> </ul> </div> `, ... };
$index 表示數組中每一項的索引值,除了 $index 以外,ng-repeat 還導出$first
、$last
、$even
和 $odd
等屬性,詳細信息能夠查看 - ngRepeat官方文檔。接下來,咱們先來看一下 $index
示例:性能優化
const app = { template: ` ... <li ng-repeat="grocery in $ctrl.groceries"> <a href="" ng-click="$ctrl.selectGrocery(grocery);"> {{ grocery.label }} {{ $index }} </a> </li> ... `, ... };
在設置 ng-repeat
初始數據時,你可能已經注意到了, this.groceries
數組中的每一項都有一個惟一的 id
屬性,基於這個惟一的屬性,咱們能夠經過 ng-repeat
指令提供的 track by
表達式,進行頁面性能優化,防止 Angular 從新渲染整個列表。即不是每次銷燬和重建列表相關的 DOM 樹,而是從新渲染那些須要更新的 DOM 元素。
const app = { template: ` ... <li ng-repeat="grocery in $ctrl.groceries track by grocery.id"> <a href="" ng-click="$ctrl.selectGrocery(grocery);"> {{ grocery.label }} {{ $index }} </a> </li> ... `, ... };
此外 track by 也支持函數表達式:
const app = { template: ` ... <li ng-repeat="grocery in $ctrl.groceries track by trackByGrocery(grocery)"> <a href="" ng-click="$ctrl.selectGrocery(grocery);"> {{ grocery.label }} {{ $index }} </a> </li> ... `, ... };
Angular 2.x 中不存在 ng-repeat
指令,取而代之的是 ngFor
指令。它們的語法很是類似,但須要注意的一點在遍歷集合是,Angular 2 使用 of
代替了 in
。
interface Grocery { id: number; label: string; } export default class AppComponent { public groceries: Grocery[]; public selectedGrocery: Grocery; constructor() { this.groceries = [{ id: 0, label: 'Butter' },{ id: 1, label: 'Apples' },{ id: 2, label: 'Paprika' },{ id: 3, label: 'Potatoes' },{ id: 4, label: 'Oatmeal' },{ id: 5, label: 'Spaghetti' },{ id: 6, label: 'Pears' },{ id: 7, label: 'Bacon' }]; this.selectGrocery(this.groceries[0]); } selectGrocery(grocery: Grocery) { this.selectedGrocery = grocery; } }
設置好初始化數據,接下來咱們來使用 ngFor
指令,須要注意的是在模板中,咱們須要使用 let
關鍵字建立局部做用域,具體示例以下:
import { Component } from '@angular/core'; interface Grocery { id: number; label: string; } @Component({ selector: 'exe-app', template: ` <div> Grocery selected: {{ selectedGrocery.label }} <ul> <li *ngFor="let grocery of groceries;"> <a href="#" (click)="selectGrocery(grocery);"> {{ grocery.label }} </a> </li> </ul> </div> ` }) export class AppComponent { public groceries: Grocery[]; public selectedGrocery: Grocery; constructor() { this.groceries = [{ id: 0, label: 'Butter' },{ id: 1, label: 'Apples' },{ id: 2, label: 'Paprika' },{ id: 3, label: 'Potatoes' },{ id: 4, label: 'Oatmeal' },{ id: 5, label: 'Spaghetti' },{ id: 6, label: 'Pears' },{ id: 7, label: 'Bacon' }]; this.selectGrocery(this.groceries[0]); } selectGrocery(grocery: Grocery) { this.selectedGrocery = grocery; } }
細心的讀者,可能會注意到模板中 *ngFor
語法,ngFor 指令前面的 *
號是語法糖,表示使用 <template>
元素。詳細內容,咱們會在 "我有話說" 章節介紹。
在 Angular 1.x 中咱們能夠直接 $index 訪問到列表項的索引值,但在 Angular 2 中,咱們使用 index 以前,咱們必須先把它賦值給其它變量,具體示例以下:
@Component({ selector: 'exe-app', template: ` <div> Grocery selected: {{ selectedGrocery.label }} <ul> <li *ngFor="let grocery of groceries; let i = index;"> <a href="#" (click)="selectGrocery(grocery);"> {{ grocery.label }} {{ i }} </a> </li> </ul> </div> ` }) export default class AppComponent {...}
介紹完 ngFor 中的 index
用法,接下來咱們來看一下 trackBy
用法。在 Angular 2 中不支持 Angular 1.x 中的 track by x
如:track by grocery.id 語法, trackBy
只支持函數。咱們來看一下具體示例:
@Component({ selector: 'exe-app', template: ` <div> Grocery selected: {{ selectedGrocery.label }} <ul> <li *ngFor="let grocery of groceries; let i = index; trackBy: trackByGrocery;"> <a href="#" (click)="selectGrocery(grocery);"> {{ grocery.label }} {{ i }} </a> </li> </ul> </div> ` }) export default class AppComponent { ... trackByGrocery: (index: number, grocery: Grocery): number => grocery.id; ... }
完整示例以下:
import { Component } from '@angular/core'; interface Grocery { id: number; label: string; } @Component({ selector: 'exe-app', template: ` <div> Grocery selected: {{ selectedGrocery.label }} <ul> <li *ngFor="let grocery of groceries; let i = index; trackBy: trackByGrocery;"> <a href="#" (click)="selectGrocery(grocery);"> {{ grocery.label }} {{ i }} </a> </li> </ul> </div> ` }) export class AppComponent { public groceries: Grocery[]; public selectedGrocery: Grocery; constructor() { this.groceries = [{ id: 0, label: 'Butter' }, { id: 1, label: 'Apples' }, { id: 2, label: 'Paprika' }, { id: 3, label: 'Potatoes' }, { id: 4, label: 'Oatmeal' }, { id: 5, label: 'Spaghetti' }, { id: 6, label: 'Pears' }, { id: 7, label: 'Bacon' }]; this.selectGrocery(this.groceries[0]); } selectGrocery(grocery: Grocery) { this.selectedGrocery = grocery; } trackByGrocery(index: number, grocery: Grocery): number { return grocery.id } }
1.Angular 2 指令有幾種分類?
在 Angular 2 指令分爲三類:
組件(Component directive):用於構建UI組件,繼承於 Directive 類
屬性指令(Attribute directive): 用於改變組件的外觀或行爲
結構指令(Structural directive): 用於動態添加或刪除DOM元素來改變DOM佈局
詳細內容請參考 - Angular 2 Directive
2.Angular 2 中的模板語法有哪一些?
Angular 2 中沒有 Angular 1.x ng-click
、ng-bind
、ng-show
等指令,取而代之的是新的模板語法。
2.1 屬性綁定:
<show-title [title]="title"></show-title>
2.2 事件綁定:
<a href="#" (click)="selectGrocery(grocery);"> {{ grocery.label }} {{ i }} </a>