# 理解模板变量

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

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

  • 模板中的 DOM 元素

  • 指令或组件

  • 来自 ng-templateTemplateRef

  • Web 组件

TIP

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

# 前提条件

  • 了解模板

# 语法

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

src/app/app.component.html

<input #phone placeholder="phone number" />

可以在组件模板中的任何地方引用某个模板变量。这里的 &lt;button&gt;就引用了 phone变量。

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 type="button" (click)="callPhone(phone.value)">Call</button>

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

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

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

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

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

# 指定名称的变量

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

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

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

src/app/hero-form.component.html

<form #itemForm="ngForm" (ngSubmit)="onSubmit(itemForm)">
  <label for="name">Name</label>
  <input type="text" id="name" class="form-control" name="name" ngModel required />
  <button type="submit">Submit</button>
</form>

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

如果没有 ngForm这个属性值,itemForm引用的值将是 HTMLFormElement 也就是 &lt;form&gt;元素。如果某元素是一个 Angular 组件,则不带属性值的引用会自动引用此组件的实例。否则,不带属性值的引用会引用此 DOM 元素,而不管此元素上有一个或多个指令。

# 模板变量的作用域

就像 JavaScript 或 TypeScript 代码中的变量一样,模板变量的范围为声明它们的模板。

同样,诸如 *ngIf*ngFor类的结构指令或 &lt;ng-template&gt;声明会创建一个新的嵌套模板范围,就像 JavaScript 的控制流语句(例如 iffor创建新的词法范围。你不能从边界外访问这些结构指令之一中的模板变量。

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

# 在嵌套模板中访问

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

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

src/app/app.component.html

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

在这种情况下,&lt;span&gt;上的 *ngIf会创建一个新的模板范围,其中包括其父范围中的 ref1变量。

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

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

在这里,ref2是在 *ngIf创建的子范围中声明的,并且无法从父模板访问。

# 模板输入变量

模板输入变量是一个具有在创建该模板实例时设置的值的变量。请参阅:编写结构指令

可以在 NgFor的长格式用法中看到模板输入变量的作用:

<ul>
  <ng-template ngFor let-hero [ngForOf]="heroes">
    <li>{{hero.name}}
  </ng-template>
</ul>

NgFor指令将实例化此为 hero 数组中的每个 heroes一次,并将为每个实例相应地设置 hero变量。

实例化 &lt;ng-template&gt;时,可以传递多个命名值,这些值可以绑定到不同的模板输入变量。输入变量的 let-声明的右侧可以指定应该用于该变量的值。

例如,NgFor还提供了对数组中每个英雄的 index的访问:

<ul>
  <ng-template ngFor let-hero let-i="index" [ngForOf]="heroes">
    <li>Hero number {{i}}: {{hero.name}}
  </ng-template>
</ul>

# 下一步呢?

编写结构指令

Last Updated: 5/13/2023, 10:57:08 AM