用戶的操做,如點擊連接,按下按鈕,輸入文字引起DOM事件。 本頁說明如何使用Angular事件綁定語法將這些事件綁定到組件事件處理程序。html
您可使用Angular事件綁定來響應任何DOM事件。 許多DOM事件由用戶輸入觸發。 綁定到這些事件提供了從用戶得到輸入的方法。git
要綁定到DOM事件,請在括號中包圍DOM事件名稱,併爲其分配引用的模板語句。 如下示例顯示了實現click處理程序的事件綁定:github
<button (click)="onClickMe()">Click me!</button>
等號左邊的(click)標識按鈕的點擊事件做爲綁定的目標。 等號右邊的引號中的文本是模板語句,它經過調用組件的onClickMe()方法來響應click事件。web
在編寫綁定時,請注意模板語句的執行上下文。 模板語句中的標識符屬於特定的上下文對象,一般是控制模板的Angular組件。 上面的例子顯示了一行HTML,可是HTML屬於一個更大的組件:異步
lib/src/click_me_component.dart (component)ide
@Component( selector: 'click-me', template: ''' <button (click)="onClickMe()">Click me!</button> {{clickMessage}} ''', ) class ClickMeComponent { String clickMessage = ''; void onClickMe() => clickMessage = 'You are my hero!'; }
當用戶點擊按鈕時,Angular從ClickMeComponent調用onClickMe()方法。oop
DOM事件攜帶可能對組件有用的信息的有效載荷。 本節介紹如何綁定到輸入框的按鍵事件,以在每次按鍵後獲取用戶的輸入。ui
下面的代碼監聽一個keyup事件,並將整個事件有效載荷($ event)傳遞給組件事件處理程序。spa
lib/src/keyup_components.dart (v1 template)
template: ''' <input (keyup)="onKey(\$event)"> <p>{{values}}</p> ''',
$EVENT VS. \$EVENT
Dart文件中的非原始字符串須要$前面的\。 若是模板位於HTML文件中,請使用$ event而不是\ $event。
當用戶按下並釋放一個鍵時,會發生一個鍵盤事件,而Angular在$ event變量中提供一個相應的DOM事件對象,該代碼將該代碼做爲參數傳遞給組件的onKey()方法。
lib/src/keyup_components.dart (v1 class, untyped)
class KeyUp1Component { String values = ''; void onKey(dynamic event) { values += event.target.value + ' | '; } }
$ event對象的屬性取決於DOM事件的類型。 例如,鼠標事件包含與輸入框編輯事件不一樣的信息。
全部標準的DOM Event對象都有一個target屬性,它是引起事件的元素的引用。 在這種狀況下,target指向<input>元素,event.target.value返回該元素的當前內容。
每次調用以後,onKey()方法將輸入框值附加到組件的values屬性,後跟一個分隔符(|)。 該模板使用Angular插值({{...}})來顯示值屬性。
假設用戶輸入字母「abc」,而後退格逐一刪除。 如下是UI顯示的內容:
a | ab | abc | ab | a | |
或者,您能夠經過用event.key替換event.target.value來累積每一個Key。 在這種狀況下,相同的用戶輸入會產生如下結果:
a | b | c | Backspace | Backspace | Backspace |
上面的例子聲明瞭onKey()事件參數是動態的。 雖然這簡化了一些代碼,但使用更具體的類型能夠揭示事件對象的屬性並防止愚蠢的錯誤。
如下示例用類型重寫該方法:lib/src/keyup_components.dart (v1 class)
class KeyUp1Component { String values = ''; void onKey(KeyboardEvent event) { InputElement el = event.target; values += '${el.value} | '; } }
如今,事件被聲明爲KeyboardEvent,event.target做爲InputElement - 具備value屬性的元素類型之一。 有了這些類型,onKey()方法就能夠更清楚地表達它對模板的指望,以及它如何解釋事件。
鍵入事件對象揭示了將整個DOM事件傳遞到方法中的一個重要問題:組件與模板細節密切相關。 若是不使用Web API,組件將沒法提取數據。 這打破了模板(用戶看到的)和組件(應用程序如何處理用戶數據)之間的關係分離。
下一節將介紹如何使用模板引用變量來解決這個問題。
還有另外一種獲取用戶數據的方法:Angular 模板引用變量提供了對模板內的元素的直接訪問。 要聲明模板引用變量,請在標識符前加一個哈希字符(#)。
如下示例使用模板引用變量在簡單模板中實現按鍵回送。
lib/src/loop_back_component.dart
@Component( selector: 'loop-back', template: ''' <input #box (keyup)="0"> <p>{{box.value}}</p> ''', ) class LoopBackComponent {}
名爲box的模板引用變量在<input>元素上聲明,引用<input>元素自己。 代碼使用box變量來獲取輸入元素的值,並在<p>標籤之間進行插值顯示。
模板是徹底獨立的。 它不綁定到組件,組件什麼也不作。
在輸入框中輸入內容,而後觀看每一個按鍵顯示更新。
除非你綁定一個事件,不然這根本不起做用。
Angular僅在應用程序響應異步事件(如擊鍵)時才更新綁定(以及屏幕)。 這個例子綁定了keyup事件到數字0,儘量最短的模板語句。 雖然該聲明沒有任何用處,但符合Angular的要求,因此Angular將更新屏幕。
使用模板引用變量到達輸入框比經過$ event對象更容易。 這裏是重寫前一個使用模板引用變量來獲取用戶輸入的關鍵示例。lib/src/keyup_components.dart (v2)
@Component( selector: 'key-up2', template: ''' <input #box (keyup)="onKey(box.value)"> <p>{{values}}</p> ''', ) class KeyUp2Component { String values = ''; void onKey(value) => values += '$value | '; }
這種方法的一個很好的方面是該組件從視圖中獲取乾淨的數據值。 它再也不須要了解$event及其結構的知識。
(keyup)事件處理程序聽到每一個擊鍵。 有時只有Enter鍵很重要,由於它表示用戶已經完成打字。 減小噪音的一種方法是檢查每一個$ event.keyCode,而且只有當輸入鍵是enter時才採起行動。
有一個更簡單的方法:綁定到Angular的keyup.enter僞事件。 而後,只有當用戶按下Enter時,Angular纔會調用事件處理程序。
lib/src/keyup_components.dart (v3)
@Component( selector: 'key-up3', template: ''' <input #box (keyup.enter)="values=box.value"> <p>{{values}}</p> ''', ) class KeyUp3Component { String values = ''; }
這是如何工做的。
在前面的示例中,若是用戶在沒有首先按下Enter的狀況下單擊頁面上的其餘位置,則輸入框的當前狀態將丟失。 只有當用戶按下Enter時,組件的value屬性纔會更新。
要解決此問題,請同時聽取Enter鍵和blur事件。
lib/src/keyup_components.dart (v4)
@Component( selector: 'key-up4', template: ''' <input #box (keyup.enter)="values=box.value" (blur)="values=box.value"> <p>{{values}}</p> ''', ) class KeyUp4Component { String values = ''; }
上一頁顯示瞭如何顯示數據。 本頁展現了事件綁定技術。
如今,把它放在一個微型應用程序,能夠顯示英雄列表,並添加新的英雄列表。 用戶能夠經過在輸入框中輸入英雄的名字並點擊添加來添加英雄。
下面是「英雄之旅」組件。
lib / src / little_tour_component.dart(little-tour)
@Component( selector: 'little-tour', template: ''' <input #newHero (keyup.enter)="addHero(newHero.value)" (blur)="addHero(newHero.value); newHero.value='' "> <button (click)="addHero(newHero.value)">Add</button> <ul><li *ngFor="let hero of heroes">{{hero}}</li></ul> ''', directives: const [CORE_DIRECTIVES], ) class LittleTourComponent { List<String> heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; void addHero(String newHero) { if (newHero?.length > 0) { heroes.add(newHero); } } }
使用模板變量來引用元素。 newHero模板變量引用<input>元素。 您能夠從<input>元素的任何兄弟或子元素引用newHero。
傳遞值,而不是元素。 取而代之的是將newHero傳遞給組件的addHero()方法,獲取輸入框的值並將其傳遞給addHero()。
保持模板語句簡單。 (blur)事件綁定到兩個語句。 第一個語句調用addHero()。 第二個語句newHero.value =''在新的英雄添加到列表後清除輸入框。
這裏是在這個頁面中討論的全部代碼。
lib/src/click_me_component.dart
import 'package:angular/angular.dart'; @Component( selector: 'click-me', template: ''' <button (click)="onClickMe()">Click me!</button> {{clickMessage}} ''', ) class ClickMeComponent { String clickMessage = ''; void onClickMe() => clickMessage = 'You are my hero!'; }
lib/src/keyup_components.dart
import 'dart:html'; import 'package:angular/angular.dart'; @Component( selector: 'key-up1-untyped', template: ''' <input (keyup)="onKey(\$event)"> <p>{{values}}</p> ''', ) class KeyUp1Component_untyped { String values = ''; void onKey(dynamic event) { values += event.target.value + ' | '; } } @Component( selector: 'key-up1', template: ''' <input (keyup)="onKey(\$event)"> <p>{{values}}</p> ''', ) class KeyUp1Component { String values = ''; void onKey(KeyboardEvent event) { InputElement el = event.target; values += '${el.value} | '; } } @Component( selector: 'key-up2', template: ''' <input #box (keyup)="onKey(box.value)"> <p>{{values}}</p> ''', ) class KeyUp2Component { String values = ''; void onKey(value) => values += '$value | '; } @Component( selector: 'key-up3', template: ''' <input #box (keyup.enter)="values=box.value"> <p>{{values}}</p> ''', ) class KeyUp3Component { String values = ''; } @Component( selector: 'key-up4', template: ''' <input #box (keyup.enter)="values=box.value" (blur)="values=box.value"> <p>{{values}}</p> ''', ) class KeyUp4Component { String values = ''; }
lib/src/loop_back_component.dart
import 'package:angular/angular.dart'; @Component( selector: 'loop-back', template: ''' <input #box (keyup)="0"> <p>{{box.value}}</p> ''', ) class LoopBackComponent {}
lib/src/little_tour_component.dart
import 'package:angular/angular.dart'; @Component( selector: 'little-tour', template: ''' <input #newHero (keyup.enter)="addHero(newHero.value)" (blur)="addHero(newHero.value); newHero.value='' "> <button (click)="addHero(newHero.value)">Add</button> <ul><li *ngFor="let hero of heroes">{{hero}}</li></ul> ''', directives: const [CORE_DIRECTIVES], ) class LittleTourComponent { List<String> heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; void addHero(String newHero) { if (newHero?.length > 0) { heroes.add(newHero); } } }
您已經看到了用於響應用戶輸入和手勢的基本原語。
這些技術對於小型演示頗有用,可是在處理大量的用戶輸入時會很快變得冗長和笨拙。 雙向數據綁定是在數據輸入字段和模型屬性之間移動值的更優雅和緊湊的方式。 下一頁,Forms介紹瞭如何使用NgModel編寫雙向綁定。