# 理解模板变量
模板变量可以帮助你在模板的另一部分使用这个部分的数据。使用模板变量,你可以执行某些任务,比如响应用户输入或微调应用的表单。
模板变量可以引用这些东西:
模板中的 DOM 元素
指令或组件
来自
ng-template
的TemplateRef
Web 组件
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>
# 下一步呢?
编写结构指令