填写这份《一分钟调查》,帮我们(开发组)做得更好!去填写Home

插值与模板表达式

Interpolation and template expressions

插值能让你把计算后的字符串合并到 HTML 元素标签之间和属性赋值语句内的文本中。模板表达式则是用来供你求出这些字符串的。

Interpolation allows you to incorporate calculated strings into the text between HTML element tags and within attribute assignments. Template expressions are what you use to calculate those strings.

要了解本指南中涉及的语法和代码片段,请参阅现场演练 / 下载范例

See the现场演练 / 下载范例for all of the syntax and code snippets in this guide.

插值 {{...}}

Interpolation {{...}}

所谓 "插值" 是指将表达式嵌入到标记文本中。 默认情况下,插值会用双花括号 {{}} 作为分隔符。

Interpolation refers to embedding expressions into marked up text. By default, interpolation uses as its delimiter the double curly braces, {{ and }}.

在下面的代码片段中,{{ currentCustomer }} 就是插值的例子。

In the following snippet, {{ currentCustomer }} is an example of interpolation.

<h3>Current customer: {{ currentCustomer }}</h3>
src/app/app.component.html
      
      <h3>Current customer: {{ currentCustomer }}</h3>
    

花括号之间的文本通常是组件属性的名字。Angular 会把这个名字替换为响应组件属性的字符串值。

The text between the braces is often the name of a component property. Angular replaces that name with the string value of the corresponding component property.

<p>{{title}}</p> <div><img src="{{itemImageUrl}}"></div>
src/app/app.component.html
      
      <p>{{title}}</p>
<div><img src="{{itemImageUrl}}"></div>
    

在上面的示例中,Angular 计算 titleitemImageUrl 属性并填充空白,首先显示一些标题文本,然后显示图像。

In the example above, Angular evaluates the title and itemImageUrl properties and fills in the blanks, first displaying some title text and then an image.

一般来说,括号间的素材是一个模板表达式,Angular 先对它求值,再把它转换成字符串。 下列插值通过把括号中的两个数字相加说明了这一点:

More generally, the text between the braces is a template expression that Angular first evaluates and then converts to a string. The following interpolation illustrates the point by adding two numbers:

<!-- "The sum of 1 + 1 is 2" --> <p>The sum of 1 + 1 is {{1 + 1}}.</p>
src/app/app.component.html
      
      <!-- "The sum of 1 + 1 is 2" -->
<p>The sum of 1 + 1 is {{1 + 1}}.</p>
    

这个表达式可以调用宿主组件的方法,就像下面用的 getVal()

The expression can invoke methods of the host component such as getVal() in the following example:

<!-- "The sum of 1 + 1 is not 4" --> <p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
src/app/app.component.html
      
      <!-- "The sum of 1 + 1 is not 4" -->
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
    

Angular 对所有双花括号中的表达式求值,把求值的结果转换成字符串,并把它们跟相邻的字符串字面量连接起来。最后,把这个组合出来的插值结果赋给元素或指令的属性

Angular evaluates all expressions in double curly braces, converts the expression results to strings, and links them with neighboring literal strings. Finally, it assigns this composite interpolated result to an element or directive property.

你看上去似乎正在将结果插入元素标签之间,并将其赋值给属性。 但实际上,插值是一种特殊语法,Angular 会将其转换为属性绑定

You appear to be inserting the result between element tags and assigning it to attributes. However, interpolation is a special syntax that Angular converts into a property binding.

如果你想用别的分隔符来代替 {{}},也可以通过 Component 元数据中的 interpolation 选项来配置插值分隔符。

If you'd like to use something other than {{ and }}, you can configure the interpolation delimiter via the interpolation option in the Component metadata.

模板表达式

Template expressions

模板表达式会产生一个值,并出现在双花括号 {{ }} 中。 Angular 执行这个表达式,并把它赋值给绑定目标的属性,这个绑定目标可能是 HTML 元素、组件或指令。

A template expression produces a value and appears within the double curly braces, {{ }}. Angular executes the expression and assigns it to a property of a binding target; the target could be an HTML element, a component, or a directive.

{{1 + 1}} 中所包含的模板表达式是 1 + 1。 在属性绑定中会再次看到模板表达式,它出现在 = 右侧的引号中,就像这样:[property]="expression"

The interpolation braces in {{1 + 1}} surround the template expression 1 + 1. In the property binding, a template expression appears in quotes to the right of the = symbol as in [property]="expression".

在语法上,模板表达式与 JavaScript 很像。很多 JavaScript 表达式都是合法的模板表达式,但也有一些例外。

In terms of syntax, template expressions are similar to JavaScript. Many JavaScript expressions are legal template expressions, with a few exceptions.

你不能使用那些具有或可能引发副作用的 JavaScript 表达式,包括:

You can't use JavaScript expressions that have or promote side effects, including:

  • 赋值 (=, +=, -=, ...)

    Assignments (=, +=, -=, ...)

  • newtypeofinstanceof 等运算符。

    Operators such as new, typeof, instanceof, etc.

  • 使用 ;, 串联起来的表达式

    Chaining expressions with ; or ,

  • 自增和自减运算符:++--

    The increment and decrement operators ++ and --

  • 一些 ES2015+ 版本的运算符

    Some of the ES2015+ operators

和 JavaScript 语法的其它显著差异包括:

Other notable differences from JavaScript syntax include:

表达式上下文

Expression context

典型的表达式上下文就是这个组件实例,它是各种绑定值的来源。 在下面的代码片段中,双花括号中的 recommended 和引号中的 itemImageUrl2 所引用的都是 AppComponent 中的属性。

The expression context is typically the component instance. In the following snippets, the recommended within double curly braces and the itemImageUrl2 in quotes refer to properties of the AppComponent.

<h4>{{recommended}}</h4> <img [src]="itemImageUrl2">
src/app/app.component.html
      
      <h4>{{recommended}}</h4>
<img [src]="itemImageUrl2">
    

表达式也可以引用模板中的上下文属性,例如模板输入变量,

An expression may also refer to properties of the template's context such as a template input variable,

let customer,或模板引用变量 #customerInput

let customer, or a template reference variable, #customerInput.

<ul> <li *ngFor="let customer of customers">{{customer.name}}</li> </ul>
src/app/app.component.html (template input variable)
      
      <ul>
  <li *ngFor="let customer of customers">{{customer.name}}</li>
</ul>
    
<label>Type something: <input #customerInput>{{customerInput.value}} </label>
src/app/app.component.html (template reference variable)
      
      <label>Type something:
  <input #customerInput>{{customerInput.value}}
</label>
    

表达式中的上下文变量是由模板变量、指令的上下文变量(如果有)和组件的成员叠加而成的。 如果你要引用的变量名存在于一个以上的命名空间中,那么,模板变量是最优先的,其次是指令的上下文变量,最后是组件的成员。

The context for terms in an expression is a blend of the template variables, the directive's context object (if it has one), and the component's members. If you reference a name that belongs to more than one of these namespaces, the template variable name takes precedence, followed by a name in the directive's context, and, lastly, the component's member names.

上一个例子中就体现了这种命名冲突。组件具有一个名叫 customer 的属性,而 *ngFor 声明了一个也叫 customer 的模板变量。

The previous example presents such a name collision. The component has a customer property and the *ngFor defines a customer template variable.

{{customer.name}} 表达式中的 customer 实际引用的是模板变量,而不是组件的属性。

The customer in {{customer.name}} refers to the template input variable, not the component's property.

模板表达式不能引用全局命名空间中的任何东西,比如 windowdocument。它们也不能调用 console.logMath.max。 它们只能引用表达式上下文中的成员。

Template expressions cannot refer to anything in the global namespace, except undefined. They can't refer to window or document. Additionally, they can't call console.log() or Math.max() and they are restricted to referencing members of the expression context.

表达式使用指南

Expression guidelines

当使用模板表达式时,请遵循下列指南:

When using template expressions follow these guidelines:

简单

Simplicity

虽然也可以写复杂的模板表达式,不过最好避免那样做。

Although it's possible to write complex template expressions, it's a better practice to avoid them.

属性名或方法调用应该是常态,但偶然使用逻辑取反 ! 也是可以的。 其它情况下,应该把应用程序和业务逻辑限制在组件中,这样它才能更容易开发和测试。

A property name or method call should be the norm, but an occasional Boolean negation, !, is OK. Otherwise, confine application and business logic to the component, where it is easier to develop and test.

快速执行

Quick execution

Angular 会在每个变更检测周期后执行模板表达式。 变更检测周期会被多种异步活动触发,比如 Promise 解析、HTTP 结果、定时器时间、按键或鼠标移动。

Angular executes template expressions after every change detection cycle. Change detection cycles are triggered by many asynchronous activities such as promise resolutions, HTTP results, timer events, key presses and mouse moves.

表达式应该快速结束,否则用户就会感到拖沓,特别是在较慢的设备上。 当计算代价较高时,应该考虑缓存那些从其它值计算得出的值。

Expressions should finish quickly or the user experience may drag, especially on slower devices. Consider caching values when their computation is expensive.

没有可见的副作用

No visible side effects

模板表达式除了目标属性的值以外,不应该改变应用的任何状态。

A template expression should not change any application state other than the value of the target property.

这条规则是 Angular “单向数据流”策略的基础。 永远不用担心读取组件值可能改变另外的显示值。 在一次单独的渲染过程中,视图应该总是稳定的。

This rule is essential to Angular's "unidirectional data flow" policy. You should never worry that reading a component value might change some other displayed value. The view should be stable throughout a single rendering pass.

幂等的表达式是最理想的,因为它没有副作用,并且可以提高 Angular 的变更检测性能。 用 Angular 术语来说,幂等表达式总会返回完全相同的东西,除非其依赖值之一发生了变化。

An idempotent expression is ideal because it is free of side effects and improves Angular's change detection performance. In Angular terms, an idempotent expression always returns exactly the same thing until one of its dependent values changes.

在单独的一次事件循环中,被依赖的值不应该改变。 如果幂等的表达式返回一个字符串或数字,连续调用它两次,也应该返回相同的字符串或数字。 如果幂等的表达式返回一个对象(包括 DateArray),连续调用它两次,也应该返回同一个对象的引用

Dependent values should not change during a single turn of the event loop. If an idempotent expression returns a string or a number, it returns the same string or number when called twice in a row. If the expression returns an object, including an array, it returns the same object reference when called twice in a row.

对于 *ngFor,这种行为有一个例外。*ngFor 具有 trackBy 功能,在迭代对象时它可以处理对象的相等性。详情参见 trackBy 的 *ngFor

There is one exception to this behavior that applies to *ngFor. *ngFor has trackBy functionality that can deal with referential inequality of objects when iterating over them. See *ngFor with trackByfor details.