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

模板变量

Template variables

模板变量可以帮助你在模板的另一部分使用这个部分的数据。使用模板变量,你可以执行某些任务,比如响应用户输入或微调应用的表单。

Template variables help you use data from one part of a template in another part of the template. With template variables, you can perform tasks such as respond to user input or finely tune your application's forms.

模板变量可以引用这些东西:

A template variable can refer to the following:

本章包含代码片段的工作实例参阅现场演练 / 下载范例

See the现场演练 / 下载范例for a working example containing the code snippets in this guide.

语法

Syntax

在模板中,要使用井号 # 来声明一个模板变量。下列模板变量 #phone 语法在 <input> 元素上声明了一个名为 phone 的变量

In the template, you use the hash symbol, #, to declare a template variable. The following template variable, #phone, declares a phone variable on an <input> element.

src/app/app.component.html
      
      <input #phone placeholder="phone number" />
    

你可以在组件模板中的任何地方引用某个模板变量。这里的 <button> 就引用了 phone 变量。

You can refer to a template variable anywhere in the component's template. Here, a <button> further down the template refers to the phone variable.

src/app/app.component.html
      
      <input #phone placeholder="phone number" />

<!-- lots of other elements -->

<!-- phone refers to the input element; pass its `value` to an event handler -->
<button (click)="callPhone(phone.value)">Call</button>
    

Angular 是如何为模板变量赋值的

How Angular assigns values to template variables

Angular 根据你所声明的变量的位置给模板变量赋值:

Angular assigns a template variable a value based on where you declare the variable:

  • 如果在组件上声明变量,该变量就会引用该组件实例。

    If you declare the variable on a component, the variable refers to the component instance.

  • 如果在标准的 HTML 标记上声明变量,该变量就会引用该元素。

    If you declare the variable on a standard HTML tag, the variable refers to the element.

  • 如果你在 <ng-template> 元素上声明变量,该变量就会引用一个 TemplateRef 实例来代表此模板。关于 <ng-template> 的更多信息,请参阅结构型指令 中的 Angular 如何使用 * 语法部分。

    If you declare the variable on an <ng-template> element, the variable refers to a TemplateRef instance, which represents the template. For more information on <ng-template>, see How Angular uses the asterisk, *, syntax in Structural directives.

  • 如果该变量在右侧指定了一个名字,比如 #var="ngModel" ,那么该变量就会引用所在元素上具有这个 exportAs 名字的指令或组件。

    If the variable specifies a name on the right-hand side, such as #var="ngModel", the variable refers to the directive or component on the element with a matching exportAs name.

NgForm 与模板变量一起使用

Using NgForm with template variables

在大多数情况下,Angular 会把模板变量的值设置为它所在的元素。在前面的例子中, phone 引用的是电话号码 <input> 。该按钮的 click 处理程序会把这个 <input> 的值传给该组件的 callPhone() 方法。

In most cases, Angular sets the template variable's value to the element on which it occurs. In the previous example, phone refers to the phone number <input>. The button's click handler passes the <input> value to the component's callPhone() method.

这里的 NgForm 指令演示了如何通过引用指令的的 exportAs 名字来引用不同的值。在下面的例子中,模板变量 itemForm 在 HTML 中分别出现了三次。

The NgForm directive demonstrates getting a reference to a different value by reference a directive's exportAs name. In the following example, the template variable, itemForm, appears three times separated by HTML.

src/app/hero-form.component.html
      
      <form #itemForm="ngForm" (ngSubmit)="onSubmit(itemForm)">
  <label for="name">Name <input class="form-control" name="name" ngModel required />
  </label>
  <button type="submit">Submit</button>
</form>

<div [hidden]="!itemForm.form.valid">
  <p>{{ submitMessage }}</p>
</div>
    

如果没有 ngForm 这个属性值,itemForm 引用的值将是 HTMLFormElement 也就是 <form> 元素。而 ComponentDirective 之间的差异在于 Angular 在没有指定属性值的情况下,Angular 会引用 Component,而 Directive 不会改变这种隐式引用(即它的宿主元素)。

Without the ngForm attribute value, the reference value of itemForm would be the HTMLFormElement, <form>. There is, however, a difference between a Component and a Directive in that Angular references a Component without specifying the attribute value, and a Directive does not change the implicit reference, or the element.

而使用了 NgForm 之后,itemForm 就是对 NgForm 指令的引用,可以用它来跟踪表单中每一个控件的值和有效性。

With NgForm, itemForm is a reference to the NgForm directive with the ability to track the value and validity of every control in the form.

与原生的 <form> 元素不同, NgForm 指令有一个 form 属性。如果 itemForm.form.valid 无效,那么 NgFormform 属性就会让你禁用提交按钮。

Unlike the native <form> element, the NgForm directive has a form property. The NgForm form property allows you to disable the submit button if the itemForm.form.valid is invalid.

模板变量的作用域

Template variable scope

你可以在包含此模板变量的模板中的任何地方引用它。而 结构型指令(如 *ngIf*ngFor<ng-template> 同样充当了模板的边界。你不能在这些边界之外访问其中的模板变量。

You can refer to a template variable anywhere within its surrounding template. Structural directives, such as *ngIf and *ngFor, or <ng-template> act as a template boundary. You cannot access template variables outside of these boundaries.

同名变量在模板中只能定义一次,这样运行时它的值就是可预测的。

Define a variable only once in the template so the runtime value remains predictable.

在嵌套模板中访问

Accessing in a nested template

内部模板可以访问外模板定义的模板变量。

An inner template can access template variables that the outer template defines.

在下面的例子中,修改 <input> 中的文本值也会改变 <span> 中的值,因为 Angular 会立即通过模板变量 ref1 来更新这种变化。

In the following example, changing the text in the <input> changes the value in the <span> because Angular immediately updates changes through the template variable, ref1.

src/app/app.component.html
      
      <input #ref1 type="text" [(ngModel)]="firstExample" />
<span *ngIf="true">Value: {{ ref1.value }}</span>
    

在这种情况下,有一个包含这个 <span> 的隐式 <ng-template>,而该变量的定义在该隐式模板之外。访问父模板中的模板变量是可行的,因为子模板会从父模板继承上下文。

In this case, there is an implied <ng-template> around the <span> and the definition of the variable is outside of it. Accessing a template variable from the parent template works because the child template inherits the context from the parent template.

我们用更啰嗦的形式重写上述的代码,可以明确地显示出 <ng-template>

Rewriting the above code in a more verbose form explicitly shows the <ng-template>.

      
      <input #ref1 type="text" [(ngModel)]="firstExample" />

<!-- New template -->
<ng-template [ngIf]="true">
  <!-- Since the context is inherited, the value is available to the new template -->
  <span>Value: {{ ref1.value }}</span>
</ng-template>
    

但是,从外部的父模板访问本模板中的变量是行不通的。

However, accessing a template variable from outside the parent template doesn't work.

      
      <input *ngIf="true" #ref2 type="text" [(ngModel)]="secondExample" />
<span>Value: {{ ref2?.value }}</span> <!-- doesn't work -->
    

这个更啰嗦的形式表明 ref2 位于外部的父模板中。

The verbose form shows that ref2 is outside the parent template.

      
      <ng-template [ngIf]="true">
  <!-- The reference is defined within a template -->
  <input #ref2 type="text" [(ngModel)]="secondExample" />
</ng-template>
<!-- ref2 accessed from outside that template doesn't work -->
<span>Value: {{ ref2?.value }}</span>
    

考虑下面这个带 *ngFor 的使用范例。

Consider the following example that uses *ngFor.

      
      <ng-container *ngFor="let i of [1,2]">
  <input #ref type="text" [value]="i" />
</ng-container>
{{ ref.value }}
    

这里,ref.value 不起作用。结构型指令 *ngFor 将模板实例化了两次,因为 *ngFor 在对数组中的两个条目进行迭代。因此不可能定义出 ref.value 指向的是谁。

Here, ref.value doesn't work. The structural directive, *ngFor instantiates the template twice because *ngFor iterates over the two items in the array. It is impossible to define what the ref.value reference signifies.

对于结构型指令,比如 *ngFor*ngIf ,Angular 也无法知道模板是否曾被实例化过。

With structural directives, such as *ngFor or *ngIf, there is no way for Angular to know if a template is ever instantiated.

结果,Angular 无法访问该值并返回错误。

As a result, Angular isn't able to access the value and returns an error.

访问 <ng-template> 的模板变量

Accessing a template variable within <ng-template>

<ng-template> 上声明变量时,该变量会引用一个 TemplateRef 实例来表示该模板。

When you declare the variable on an <ng-template>, the variable refers to a TemplateRef instance, which represents the template.

src/app/app.component.html
      
      <ng-template #ref3></ng-template>
<button (click)="log(ref3)">Log type of #ref</button>
    

在这个例子中,单击该按钮会调用 log() 函数,它把 #ref3 的值输出到控制台。因为 #ref 变量在 <ng-template> 上,所以它的值是一个 TemplateRef

In this example, clicking the button calls the log() function, which outputs the value of #ref3 to the console. Because the #ref variable is on an <ng-template>, the value is TemplateRef.

下面是一个名为 TemplateRefTemplateRef() 函数在浏览器控制台中展开时的输出。

The following is the expanded browser console output of the TemplateRef() function with the name of TemplateRef.

      
       ƒ TemplateRef()
name: "TemplateRef"
__proto__: Function
    

模板输入变量

Template input variable

模板输入变量是可以在模板的单个实例中引用的变量。你可以用 let 关键字声明模板输入变量,比如 let hero

A template input variable is a variable you can reference within a single instance of the template. You declare a template input variable using the let keyword as in let hero.

在这个例子中,有几个这样的变量:heroiodd

There are several such variables in this example: hero, i, and odd.

此变量的范围仅限于可复写模板中的单个实例。你可以在其他结构型指令的定义中再次使用相同的变量名。

The variable's scope is limited to a single instance of the repeated template. You can use the same variable name again in the definition of other structural directives.

相反,你可以通过在变量名称前加上 # 来声明模板变量,如 #var。模板变量引用其附加的元素、组件或指令。

In contrast, you declare a template variable by prefixing the variable name with #, as in #var. A template variable refers to its attached element, component, or directive.

模板输入变量和模板变量名称具有各自的名称空间。let hero 中的模板输入变量 hero#hero 中的模板变量 hero 是不同的。

Template input variables and template variables names have their own namespaces. The template input variable hero in let hero is distinct from the template variable hero in #hero.