用户的操做,如点击连接,按下按钮,输入文字引起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编写双向绑定。