创建一个class类
ng generate class hero
export class Hero {
constructor(
public id: number,
public name: string) { }
}
迭代
<li *ngFor="let hero of heroes">
{{ hero }}
</li>
HTML 的 value 这个 attribute 指定了初始值;DOM 的 value 这个 property 是当前值。
这句话值得再强调一次: 模板绑定是通过 property 和事件来工作的,而不是 attribute。
更多详情
https://angular.cn/guide/template-syntax
这些方法都有价值,但是会显得笨重,特别是当这个属性路径非常长的时候。 想象一下在一个很长的属性路径(如 a.b.c.d)中对空值提供保护。
Angular 安全导航操作符 (?.) 是在属性路径中保护空值的更加流畅、便利的方式。 表达式会在它遇到第一个空值的时候跳出。 显示是空的,但应用正常工作,而没有发生错误。
src/app/app.component.html
content_copy
The null hero’s name is {{nullHero?.name}}
在像 a?.b?.c?.d 这样的长属性路径中,它工作得很完美。back to top
非空断言操作符(!)
在 TypeScript 2.0 中,你可以使用 --strictNullChecks 标志强制开启严格空值检查。TypeScript 就会确保不存在意料之外的 null 或 undefined。
在这种模式下,有类型的变量默认是不允许 null 或 undefined 值的,如果有未赋值的变量,或者试图把 null 或 undefined 赋值给不允许为空的变量,类型检查器就会抛出一个错误。
如果类型检查器在运行期间无法确定一个变量是 null 或 undefined,那么它也会抛出一个错误。 你自己可能知道它不会为空,但类型检查器不知道。 所以你要告诉类型检查器,它不会为空,这时就要用到非空断言操作符。
Angular 模板中的**非空断言操作符(!)也是同样的用途。
例如,在用*ngIf来检查过 hero 是已定义的之后,就可以断言 hero 属性一定是已定义的。
src/app/app.component.html
content_copy
与安全导航操作符不同的是,非空断言操作符不会防止出现 null 或 undefined。 它只是告诉 TypeScript 的类型检查器对特定的属性表达式,不做 “严格空值检测”。
如果你打开了严格控制检测,那就要用到这个模板操作符,而其它情况下则是可选的。
类型转换函数
a
n
y
(
any (
any(any( <表达式> ))
有时候,绑定表达式可能会报类型错误,并且它不能或很难指定类型。要消除这种报错,你可以使用 $any 转换函数来把表达式转换成 any 类型。
src/app/app.component.html
content_copy
$any 转换函数可以和 this 联合使用,以便访问组件中未声明过的成员。
src/app/app.component.html
content_copy
小结
你完成了模板语法的概述。现在,该把如何写组件和指令的知识投入到实际工作当中了。
通过 $event 对象取得用户输入
DOM 事件可以携带可能对组件有用的信息。 本节将展示如何绑定输入框的 keyup 事件,在每个敲击键盘时获取用户输入。
下面的代码监听 keyup 事件,并将整个事件载荷 ($event) 传递给组件的事件处理器。
src/app/keyup.components.ts (template v.1)
content_copy
template: `
<input (keyup)=“onKey($event)”>
{{values}}
` 当用户按下并释放一个按键时,触发 keyup 事件,Angular 在 $event 变量提供一个相应的 DOM 事件对象,上面的代码将它作为参数传递给 onKey() 方法。从一个模板引用变量中获得用户输入
还有另一种获取用户数据的方式:使用 Angular 的模板引用变量。 这些变量提供了从模块中直接访问元素的能力。 在标识符前加上井号 (#) 就能声明一个模板引用变量。
下面的例子使用了局部模板变量,在一个超简单的模板中实现按键反馈功能。
src/app/loop-back.component.ts
content_copy
@Component({
selector: ‘app-loop-back’,
template: <input #box (keyup)="0"> <p>{{box.value}}</p>
})
export class LoopbackComponent { }
这个模板引用变量名叫 box,在 元素声明,它引用 元素本身。 代码使用 box 获得输入元素的 value 值,并通过插值表达式把它显示在
标签中。
这个模板完全是完全自包含的。它没有绑定到组件,组件也没做任何事情。
在输入框中输入,就会看到每次按键时,显示也随之更新了。
按键事件过滤(通过 key.enter)
(keyup) 事件处理器监听每一次按键。 有时只在意回车键,因为它标志着用户结束输入。 解决这个问题的一种方法是检查每个 $event.keyCode,只有键值是回车键时才采取行动。
更简单的方法是:绑定到 Angular 的 keyup.enter 模拟事件。 然后,只有当用户敲回车键时,Angular 才会调用事件处理器。
src/app/keyup.components.ts (v3)
content_copy
@Component({
selector: ‘app-key-up3’,
template: <input #box (keyup.enter)="onEnter(box.value)"> <p>{{value}}</p>
})
export class KeyUpComponent_v3 {
value = ‘’;
onEnter(value: string) { this.value = value; }
}
下面展示了它是如何工作的。
key up 3
失去焦点事件 (blur)
前上例中,如果用户没有先按回车键,而是移开了鼠标,点击了页面中其它地方,输入框的当前值就会丢失。 只有当用户按下了回车键候,组件的 values 属性才能更新。
下面通过同时监听输入框的回车键和失去焦点事件来修正这个问题。
src/app/keyup.components.ts (v4)
content_copy
@Component({
selector: ‘app-key-up4’,
template: `
<input #box
(keyup.enter)=“update(box.value)”
(blur)=“update(box.value)”>
<p>{{value}}</p>
`
})
export class KeyUpComponent_v4 {
value = ‘’;
update(value: string) { this.value = value; }
}
把它们放在一起
Put it all together
上一章介绍了如何显示数据。 本章展示了事件绑定技术。
现在,在一个微型应用中一起使用它们,应用能显示一个英雄列表,并把新的英雄加到列表中。 用户可以通过输入英雄名和点击“添加”按钮来添加英雄。
Little Tour of Heroes
下面就是“简版英雄指南”组件。
src/app/little-tour.component.ts
content_copy
@Component({
selector: ‘app-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>
`
})
export class LittleTourComponent {
heroes = [‘Windstorm’, ‘Bombasto’, ‘Magneta’, ‘Tornado’];
addHero(newHero: string) {
if (newHero) {
this.heroes.push(newHero);
}
}
}
小结
使用模板变量来引用元素 — newHero 模板变量引用了 元素。 你可以在 的任何兄弟或子级元素中引用 newHero。
传递数值,而非元素 — 获取输入框的值并将它传递给组件的 addHero,而不要传递 newHero。
保持模板语句简单 — (blur) 事件被绑定到两个 JavaScript 语句。 第一句调用 addHero。第二句 newHero.value=’’ 在添加新英雄到列表中后清除输入框。
源代码
下面是本章讨论过的所有源码。
click-me.component.ts
keyup.components.ts
loop-back.component.ts
little-tour.component.ts
content_copy
import { Component } from ‘@angular/core’;
@Component({
selector: ‘app-click-me’,
template: <button (click)="onClickMe()">Click me!</button> {{clickMessage}}
})
export class ClickMeComponent {
clickMessage = ‘’;
onClickMe() {
this.clickMessage = ‘You are my hero!’;
}
}
小结
你已经掌握了响应用户输入和操作的基础技术。
这些技术对小规模演示很实用,但是在处理大量用户输入时,很容易变得累赘和笨拙。 要在数据录入字段和模型属性之间传递数据,双向数据绑定是更加优雅和简洁的方式。 下一章 表单 解释了如何用 NgModel 来进行双向绑定。