Angular 文本插值
文本插值
文本插值允许你将动态字符串值合并到 HTML 模板中。通过插值,你可以动态更改应用视图中显示的内容,例如显示包含用户名的自定义问候语。
要了解本指南中涉及的语法和代码片段,请参阅 现场演练 / 下载范例。
使用插值语法显示值
插值是指将表达式嵌入到被标记的文本中。默认情况下,插值使用双花括号 {{
和 }}
作为定界符。
为了说明插值的工作原理,请考虑一个包含 currentCustomer
变量的 Angular 组件:
currentCustomer = 'Maria';
可以用插值在相应的组件模板中显示此变量的值:
<h3>Current customer: {{ currentCustomer }}</h3>
Angular 会用相应组件属性的字符串值替换掉 currentCustomer
。在这里,它的值是 Maria
。
在以下示例中,Angular 会求出 title
和 itemImageUrl
属性的值,以显示一些标题文本和图像。
<p>{{title}}</p>
<div><img src="{{itemImageUrl}}"></div>
模板表达式
模板表达式会产生一个值,它出现在双花括号 {{ }}
中。 Angular 解析该表达式并将其赋值给绑定目标的某个属性。目标可以是 HTML 元素、组件或指令。
用插值解析表达式
一般来说,括号间的文本是一个模板表达式,Angular 先对它求值,再把它转换成字符串。 下列插值通过把括号中的两个数字相加说明了这一点:
<!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{1 + 1}}.</p>
这些表达式也可以调用宿主组件的方法,就像下面用的 getVal()
:
<!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
通过插值,Angular 执行以下任务:
- 计算所有位于双花括号中的表达式。
- 将这些表达式的结果转换为字符串。
- 将这些结果融入相邻的字符串文本中。
- 将融合后的结果赋值给元素或指令的属性。
如果你想用别的分隔符来代替
{{
和 }}
,也可以通过 @Component()
元数据中的 interpolation
选项来配置插值分隔符。
语法
模板表达式和 JavaScript 很相似。许多 JavaScript 表达式都是合法的模板表达式,但以下情况除外。
你不能使用那些具有或可能引发副作用的 JavaScript 表达式,包括:
- 赋值 (
=
, +=
, -=
, ...
) - 运算符,比如
new
、typeof
或 instanceof
等。 - 使用
;
或 ,
串联起来的表达式 - 自增和自减运算符:
++
和 --
- 一些 ES2015+ 版本的运算符
和 JavaScript 语法的其它显著差异包括:
- 不支持位运算,比如
|
和 &
- 新的模板表达式运算符,例如
|
,?.
和 !
表达式上下文
插值表达式具有上下文 —— 表达式所属应用中的特定部分。通常,此上下文就是组件实例。
在下面的代码片段中,表达式 recommended
和 itemImageUrl2
表达式所引用的都是 AppComponent
中的属性。
<h4>{{recommended}}</h4>
<img [src]="itemImageUrl2">
表达式也可以引用模板上下文中的属性。
下面的例子就使用了模板输入变量 customer
。
<ul>
<li *ngFor="let customer of customers">{{customer.name}}</li>
</ul>
接下来的例子使用了模板引用变量 #customerInput
。
<label>Type something:
<input #customerInput>{{customerInput.value}}
</label>
模板表达式不能引用全局命名空间中的任何东西,比如
window
或 document
。它们也不能调用 console.log
或 Math.max
。 它们只能引用表达式上下文中的成员。
防止命名冲突
表达式求值的上下文是模板变量、指令的上下文对象(如果有的话)以及组件成员的并集。如果所引用的名称在多个命名空间都有,则 Angular 将应用以下逻辑来确定上下文:
- 模板变量的名称。
- 指令上下文中的名称。
- 组件成员的名称。
为避免变量遮盖另一个上下文中的变量,请保持变量名称唯一。在以下示例中,AppComponent
模板在问候 customer
Padma。
然后,一个 ngFor
列出了 customers
数组中的每个 customer
。
@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 的单向数据流模型,除了目标属性的值之外,模板表达式不应更改任何应用状态。读取组件值不应更改其他显示值。该视图应在整个渲染过程中保持稳定。
幂等表达式能减少副作用
幂等的表达式是最理想的,因为它没有副作用,并且可以提高 Angular 的变更检测性能。 用 Angular 术语来说,幂等表达式总会返回完全相同的东西,除非其依赖值之一发生了变化。
在单独的一次事件循环中,被依赖的值不应该改变。 如果幂等的表达式返回一个字符串或数字,如果连续调用它两次,会返回相同的字符串或数字。 如果幂等的表达式返回一个对象(包括 Date
或 Array
),如果连续调用它两次,会返回同一个对象的引用。
对于
*ngFor
,这种行为有一个例外。*ngFor
具有 trackBy
功能,在迭代对象时它可以正确处理对象值的变化。