# 了解绑定
在 Angular 模板中,绑定会在从模板创建的一部分 UI(DOM 元素、指令或组件)与模型(模板所属的组件实例)之间创建实时连接。此连接可用于将视图与模型同步、在视图中发生事件或用户操作时通知模型,或两者兼而有之。Angular 的变更检测算法负责保持视图和模型的同步。
绑定的例子包括:
文本插值
属性绑定
事件绑定
双向绑定
绑定始终有两部分:将接收绑定值的目标和从模型生成值的模板表达式。
# 语法
模板表达式类似于 JavaScript 表达式。许多 JavaScript 表达式都是合法的模板表达式,但以下例外。
你不能使用那些具有或可能引发副作用的 JavaScript 表达式,包括:
赋值 (
=
,+=
,-=
,...
)运算符,比如
new
、typeof
或instanceof
等。链接表达式
;
或,
自增和自减运算符:
++
和--
一些 ES2015+ 版本的运算符
和 JavaScript 语法的其它显著差异包括:
不支持位运算,比如
|
和&
新的模板表达式运算符,比如
|
# 表达式上下文
插值表达式具有上下文 —— 表达式所属应用中的特定部分。通常,此上下文就是组件实例。
在下面的代码片段中,表达式 recommended
和 itemImageUrl2
表达式所引用的都是 AppComponent
中的属性。
src/app/app.component.html
<h4>{{recommended}}</h4>
<img alt="item 2" `src]="itemImageUrl2">
表达式还可以引用模板上下文中的属性,比如模板输入变量` 或[模板引用变量。
下面的例子就使用了模板输入变量 customer
。
src/app/app.component.html (template input variable)
<ul>
<li *ngFor="let customer of customers">{{customer.name}}</li>
</ul>
接下来的例子使用了模板引用变量 #customerInput
。
src/app/app.component.html (template reference variable)
<label>Type something:
<input #customerInput>{{customerInput.value}}
</label>
TIP
模板表达式不能引用全局命名空间中的任何东西,除了 undefined
。他们不能引用 window
或 document
。此外,它们不能调用 console.log()
或 Math.max()
,并且只能引用表达式上下文的成员。
# 防止命名冲突
表达式估算的上下文是模板变量、指令的上下文对象(如果有)和组件成员的并集。如果你引用的名称属于这些命名空间之一,则 Angular 会应用以下优先逻辑来确定上下文:
模板变量的名称。
指令上下文中的名称。
组件成员的名称。
为避免变量遮盖另一个上下文中的变量,请保持变量名称唯一。在以下示例中,AppComponent
模板在问候 customer
Padma。
然后,一个 ngFor
列出了 customers
数组中的每个 customer
。
src/app/app.component.ts
@Component({
template: `
<div>
<!-- Hello, Padma -->
<h1>Hello, {{customer}}</h1>
<ul>
<!-- Ebony and Chiho in a list-->
<li *ngFor="let customer of customers">{{ customer.value }}</li>
</ul>
</div>
`
})
class AppComponent {
customers = [{value: 'Ebony'}, {value: 'Chiho'}];
customer = 'Padma';
}
ngFor
中的 customer
处于一个 <ng-template>
的上下文中,所以它指向的是 customers
数组中的 customer
,在这里是 Ebony 和 Chiho。此列表中不包含 Padma,因为那个 customer
位于 ngFor
以外的另一个上下文中。反之,<h1>
中的 customer
不包括 Ebony 或 Chiho,因为该 customer
的上下文是组件类,而这个类中 customer
的值是 Padma。
# 表达式最佳实践
使用模板表达式时,请遵循以下最佳实践:
- 使用短表达式
尽可能使用属性名称或方法调用。将应用和业务逻辑保留在组件中,这里更便于开发和测试。
- 快速执行
Angular 会在每个变更检测周期之后执行一个模板表达式。许多异步活动会触发变更检测周期,比如 promise 解析、HTTP 结果、计时器事件、按键和鼠标移动。
表达式应该快速完成,以保持用户体验尽可能高效,在较慢的设备上尤为明显。当计算需要更多资源时,考虑缓存值。
# 没有明显的副作用
根据 Angular 的单向数据流模型,除了目标属性的值之外,模板表达式不应更改任何应用状态。读取组件值不应更改其他显示值。该视图应在整个渲染过程中保持稳定。
用幂等表达式减少副作用Idempotent expressions reduce side effects幂等
的表达式是最理想的,因为它没有副作用,并且可以提高 Angular 的变更检测性能。用 Angular 术语来说,幂等表达式总会返回完全相同的东西,除非其依赖值之一发生了变化。
在单独的一次事件循环中,被依赖的值不应该改变。如果幂等的表达式返回一个字符串或数字,如果连续调用它两次,会返回相同的字符串或数字。如果幂等的表达式返回一个对象(也包括 Array
),如果连续调用它两次,会返回同一个对象的引用。
# 下一步呢?
property 绑定
事件绑定