# 理解模板变量
模板变量可以帮助你在模板的另一部分使用这个部分的数据。使用模板变量,你可以执行某些任务,比如响应用户输入或微调应用的表单。
模板变量可以引用这些东西:
模板中的 DOM 元素
指令或组件
来自
ng-template的TemplateRefWeb 组件
TIP
本章包含代码片段的工作实例参阅现场演练/ 下载范例 。
# 前提条件
了解模板
# 语法
在模板中,要使用井号 #来声明一个模板变量。下列模板变量 #phone声明了一个名为 phone的变量,其值为此 <input>元素。
src/app/app.component.html
<input #phone placeholder="phone number" />
可以在组件模板中的任何地方引用某个模板变量。这里的 <button>就引用了 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 标记上声明变量,该变量就会引用该元素。
如果你在
<ng-template>元素上声明变量,该变量就会引用一个TemplateRef实例来代表此模板。关于<ng-template>的更多信息,请参阅结构型指令中的Angular 如何使用 * 语法部分。
# 指定名称的变量
- 如果该变量在右侧指定了一个名字,比如
#var="ngModel",那么该变量就会引用所在元素上具有这个exportAs名字的指令或组件。
# 将 NgForm与模板变量一起使用link
在大多数情况下,Angular 会把模板变量的值设置为它所在的元素。在前面的例子中,phone引用的是电话号码 <input>。该按钮的 click 处理程序会把这个 <input>的值传给该组件的 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 也就是 <form>元素。如果某元素是一个 Angular 组件,则不带属性值的引用会自动引用此组件的实例。否则,不带属性值的引用会引用此 DOM 元素,而不管此元素上有一个或多个指令。
# 模板变量的作用域
就像 JavaScript 或 TypeScript 代码中的变量一样,模板变量的范围为声明它们的模板。
同样,诸如 *ngIf和 *ngFor类的结构指令或 <ng-template>声明会创建一个新的嵌套模板范围,就像 JavaScript 的控制流语句(例如 if和 for创建新的词法范围。你不能从边界外访问这些结构指令之一中的模板变量。
同名变量在模板中只能定义一次,这样运行时它的值就是可预测的。
# 在嵌套模板中访问
内部模板可以访问外模板定义的模板变量。
在下面的例子中,修改 <input>中的文本值也会改变 <span>中的值,因为 Angular 会立即通过模板变量 ref1来更新这种变化。
src/app/app.component.html
<input #ref1 type="text" [(ngModel)]="firstExample" />
<span *ngIf="true">Value: {{ ref1.value }}</span>
在这种情况下,<span>上的 *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变量。
实例化 <ng-template>时,可以传递多个命名值,这些值可以绑定到不同的模板输入变量。输入变量的 let-声明的右侧可以指定应该用于该变量的值。
例如,NgFor还提供了对数组中每个英雄的 index的访问:
<ul>
<ng-template ngFor let-hero let-i="index" [ngForOf]="heroes">
<li>Hero number {{i}}: {{hero.name}}
</ng-template>
</ul>
# 下一步呢?
编写结构指令