继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

模板引用变量

为爱心太软
关注TA
已关注
手记 170
粉丝 1.4万
获赞 860

基本概念

模板引用变量是模板中某一元素的引用,这个元素可以是标准的 HTML 元素,可以是 Angular 组件,也可以是 ng-template 元素(angular 的结构型指令,常见于UI框架),甚至也可以是完全自定义的元素(Web Components,使用较少)。

定义模板引用变量

 # + 变量名称

例子:

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

引用标准 HTML 元素

使用模板引用变量来引用 HTML 元素,在实际开发中是十分常见的。

例子:

// html
<section>
  <input #person placeholder="" type="text" />
  <button (click)="showName(person.value)">Search</button>
</section>

// ts
showName(name:string){
  console.log(name);
}

引用 Angular 组件

通过模板引用变量,我们可以很轻松地获得组件内部的变量和方法。

例子:

// 子组件:my-component.component.html
<p>
  hello {{ name }} !
</p>

// 子组件:my-component.component.ts
name:string = 'Tom';
welcome:string = 'Welcome to China, nice to meet you!';

changeName(){
  this.name = 'Amy';
}

// html
// 引用子组件 my-component.component
<section>
  <app-my-component #person></app-my-component>

  <p>{{ person.welcome }}</p>
  <button (click)="person.changeName()">Change</button>
</section>

引用 ng-template

ng-template 是 Angular 的一个结构型指令,用于定义内嵌模板。但其定义的模板不会直接显示出来,而是需要通过 ngif 等指令或者通过 ViewContainerRef 的 createEmbeddedView() 方法将内容加载到页面上。

ng-template 与 ngif 指令

例子:

// html
<section>
  <p *ngIf="expression else myTemplate">Welcome to China</p>

  <ng-template #myTemplate>
    <p>Welcome to Korea</p>
  </ng-template>
</section>

// ts
expression = false;

例子中,如果 expression 为 true,则展示“Welcome to China”,否则展示“Welcome to Korea”。

ng-template 与 ViewContainerRef 接口

例子:

// app.component.html
<section>
  <button (click)="showMyTemplate()">show</button>
  
  <ng-template #myTemplate>
    <p>Welcome to Korea</p>
  </ng-template>
</section>

// app.component.ts

// 引入 ViewChild、TemplateRef、ViewContainerRef
// ViewChild: 装饰器,Angular 提供的元素查询工具,可以使用它在模板中查询模板引用变量
// TemplateRef: Angular 提供的内嵌模板的接口,指向 <ng-template> 元素
// ViewContainerRef: Angular 提供的用于创建和管理内嵌模板的接口
import { Component, OnInit, ViewChild, TemplateRef,  ViewContainerRef } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit {

  // 取到变量 myTemplate,类型为 TemplateRef
  @ViewChild('myTemplate')
  myRef!: TemplateRef<any>;

  constructor(
    // 初始化 ViewContainerRef 接口
    private viewRef : ViewContainerRef
  ) { }

  ngOnInit() {
  }

  showMyTemplate(){
    // 调用 ViewContainerRef 中的 createEmbeddedView() 方法
    // 将内嵌模板的内容加载到页面上
    this.viewRef.createEmbeddedView(this.myRef);
  }
}

模板引用变量的作用域

说到模板引用变量的作用域,我们就不得不重提一下结构型指令,在 Angular 中,* 符号意味着简写:

*ngIf="exp"
*ngFor="let item of [1,2,3]"

实际上,非简写的形式是围绕 ng-template 元素进行的,只是由简写转换为普通语法的过程,Angular 已经帮助我们去完成了:

<ng-template [ngIf]="exp">
<ng-template ngFor let-item [ngForOf]="[1,2,3]">

因此,在模板变量的作用域的定义中,提到了不可以在模板的外部访问该模板内部的模板变量,而找到这个内部和外部的边界,就显得尤为重要,通常可以将结构型指令(ngIf、ngFor、ng-template)当作这个边界。

例子:

// html
<section>
  <input *ngIf="true" type="text" [(ngModel)]="name" #person>
  <p>{{ person.value }}</p>
</section>

// ts
name:string = '';

如果现在无法判断是否可以访问到模板变量 person,我们可以恢复一下例子的非简写模式:

例子:

// html
<section>
  <ng-template [ngIf]="true">
    <input type="text" [(ngModel)]="name" #person>
  </ng-template>

  <p>{{ person.value }}</p>
</section>

// ts
name:string = '';

此时可以看出来,例子中,我们是在 ng-template 模板的外部(p 元素处)访问其内部的变量 person,因此是访问不到的,会报错。
再看下面的例子:

例子:

// html
<section>
  <input type="text" [(ngModel)]="name" #person>
  <p *ngIf="true">{{ person.value }}</p>
</section>

// ts
name:string = '';

将例子恢复成非简写模式:

例子:

// html
<section>
  <input type="text" [(ngModel)]="name" #person>

  <ng-template [ngIf]="true">
    <p>{{ person.value }}</p>
  </ng-template>
</section>

// ts
name:string = '';

此时,我们是在 ng-template 模板的内部访问其外部(或者叫父辈)的变量 person,根据 ES 的查询机制,这样是可行的,因此,可以访问到变量 person。


end

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP