來源:http://kittencup.com/javascript/2015/07/20/Angular%202%E6%A8%A1%E6%9D%BF%E8%AF%AD%E6%B3%95.htmljavascript
原文地址:http://victorsavkin.com/post/119943127151/angular-2-template-syntaxhtml
屬性和事件綁定在指令中是公開的API,數據從屬性綁定流入指令,從事件中流出指令java
假設咱們有一個組件來呈現的Todo,咱們能夠在咱們的模板中使用這個組件,以下所示:git
<todo-cmp [model]="myTodo"></todo-cmp>
這告訴Angular,只要myTodo發生變化,當有一個新的todo時,Angular會經過模型來自動更新todo組件github
如今,讓咱們添加一個事件使組件更有趣。web
<todo-cmp [model]="todo" (complete)="onCompletingTodo(todo)"></todo-cmp>
當事件complete觸發時會告訴Angular調用onCompletingTodo方法編程
如今,讓咱們看看TodoCmp自己。ide
@Component({ selector: 'todo-cmp', properties: ['model'], events: ['complete'] }) class TodoCmp { model; complete = new EventEmitter(); // TypeScript 支持初始化 onCompletedButton() { this.complete.next(); // 觸發事件 } }
這個組件聲明數據綁定的名字爲model,事件名爲complete工具
Angular使用Rx事件風格來處理事件的接收,EventEmitter即實現了observable,又實現了observer接口(規範),所以,咱們能夠用它來觸發事件,而且Angular也能夠用它來監聽事件。post
正如你所看到的,屬性和事件綁定的核心語法很簡單。在覈心語法之上,Angular提供了一些語法糖,使表達經常使用的編程模式更加容易。重要的是要了解,這僅僅是語法糖,並且它不會改變語義。
雙向數據綁定在某些狀況下是很方便的,最值得注意的是處理輸入,正如我剛纔提到的,屬性綁定用於數據從父傳遞給子,事件綁定用於從子到父的數據傳遞。所以,咱們可使用兩種方法來實現雙向綁定。
<input [ng-model]="todo.text" (ng-model)="todo.text=$event"></input>
雖然這能夠正常工做,但這太羅嗦。由於這是一個常見的模式,因此Angular提供語法糖簡化這種寫法。
<input [(ng-model)]="todo.text"></input>
要完成這個例子,讓咱們來實現Angular 2的ng-model
@Directive({
selector: '[ng-model]',
properties: ['ngModel'],
events: ['ngModelChanged: ngModel'],
host: {
"[value]": 'ngModel',
"(input)": "ngModelChanged.next($event.target.value)"
}
})
class NgModelDirective {
ngModel:any; // stored value
ngModelChanged:EventEmitter; // an event emitter
}
這是一種比較幼稚的ngModel實現,但它說明了如何實現雙向數據綁定行爲:輸入將在text發生更改時更新,並在輸入更改時更新text字段。
請注意,於Angular 1相反,你只要看看模板就能夠知道哪些綁定是「雙向」,哪些是「單向」。
此外,由於只有一個方向,屬性綁定,被Angular自動執行,雙向的行爲更可預測的。
它不會破壞任何Angular 2的語法:這只是一些語法糖,沒有別的。
我想提一提,你不用去實現NgModel。Angular 2配備了一個表單處理模塊,其包括NgModel的實現。
<div>Hello {{name}}</div>
使用語法糖
<div [textContent]="interpolate(['Hello'], [name])"></div>
<show-title title="Some Title"></show-title>
使用語法糖
<show-title [title]=" 'Some Title' "></show-title>
你可使用bind-,in-和bindon-在你的模板中代替全部的括號,雖然這幾乎不能稱爲「語法糖」
<some-component [prop]="someExp" (event)="someEvent()" [(two-way-prop)]="someExp"></show-title>
於上面相同
<some-component bind-prop="someExp" on-event="someEvent()" bindon-two-way-prop="someExp"></show-title>
有兩個組件互相交互,這種狀況並很多見,Angular 2在模板中支持定義的局部變量。
<video-player #player></video-player> <button (click)="player.pause()">Pause</button>
#player表示當前video-player組件自身,而沒有#player的組件則能夠經過player訪問video-player組件
<input #i> {{i.value}}
<video-player #player></video-player>
至關於
<video-player var-player></video-player>
Angular以特殊的方式對待template元素。它們用來建立視圖,你能夠動態操做DOM塊,*語法是一種捷徑,它可使你不用寫出所有的<template>
元素,讓我告訴你它是如何工做。
假設咱們呈現Todo列表組件。
<todo-cmp *ng-for="#t of todos; #i=index" [model]="t" [index]="t"></todo-cmp>
去除語法糖後變爲
<todo-cmp template="ng-for #item of items; #i=index" [model]="t" [index]="i"></todo-cmp>
再一次去除語法糖後變爲
<template ng-for #item="$implicit" [ng-for-of]="items" #i="index"> <todo-cmp [model]="t" [index]="t"></todo-cmp> </template>
該ngFor指令在視圖上會建立$implicit和$index變量並綁定到模板上,在模板元素上聲明的全部變量只能在元素內提供,這就是爲何如下是不正確
<todo-cmp *ng-for="#t of todos"></todo-cmp> {{t}} <!-- t cannot be referenced here -->
你須要重點理解的是,當你創建你本身的指令來處理視圖時,你的 * syntax 語法能擴展成什麼。例如,若是你看ngfor,你會發現它有ngforof屬性,可是沒有of屬性。
爲何不對ng-for自定義語法,象angular 1同樣呢?這有幾個很好的理由。有自定義語法意味着你必須知道這個微語言如何操做。這也意味着在工具(例如,IDE和LInter)中不能理解你的模板並且並不能提供自動完成和重構。
在這篇博客我談到了一切的內容 - 局部變量,屬性和事件綁定 - 對於web組件和標準的html元素來說使用方式是徹底相同
我能夠用Web組件更換TodoCmp,仍然使用相同方式與它進行交互。
<todo-cmp [model]="todo" (completed)="onCompletingTodo(todo)"></todo-cmp>
我能夠用Web組件更換視頻播放器,仍然使用相同方式與它進行交互。
<video-player #player></video-player> <button (click)="player.pause()">Pause</button>
這將變得極爲重要,由於更多的組件庫可用。當運行在非Angular組件上也很重要(這是Angular 2目標之一),否者你不得不把每個原生組件包裝成一個Angular 2組件,那真的很糟糕。Angular 2你能夠直接使用任何本地組件,使用相同的語法,只有當你例如想使用依賴注入時,可將它包裝爲Angular組件
我但願你能明白在Angular 2裏模板語法是怎麼運做的.如今,我想來討論一下爲何它用這種方式運做?它這麼設計的目的是什麼?
咱們的主要設計目標是使模板更加清晰,開發者在不知若是使用指令狀況也可以理解和重構模板,以及指令是如何工做的。
<component [property1]="name" property2="name"></component>
無論組件元素是什麼,property1是指向一個name變量的屬性 property2屬性只表示一個name字符串,你也須要知道,組件的property2屬性沒法更新,property1屬性綁定更新是從父到子。
<component [(property1)]="name"></component>
在這裏,咱們能夠看到,name能夠被更新,由於咱們使用[()]語法
一樣,你能夠告訴在模板中定義了哪些變量,來看這裏的*nf-for
<todo-cmp *ng-for="#t of todos"></todo-cmp>
其次,咱們但願有豐富的開發工具,在下面的列子中,工具能夠靜態地推斷出第一個index是組件上的字段,而第2個index是ng-for輸出的局部變量
{{index}}
<div *ng-for="#item of items; var index=index"> {{index} </div>
這就是其中的一個Angular 2模板的實例分析。因爲IDE能夠分析模板,因此他們能夠提供自動完成和重構。
最後,咱們要本地組件和web組件無縫集成。這意味着Angular 不能有特殊的特定事件(例如,ng-click),而必須提供通用機制,更新任何屬性或監放任何事件。