本文将向您介绍 Angular 的 ViewChild 装饰器。
在某些情况下,您可能希望从父组件类中访问指令、子组件或 DOM 元素。ViewChild 装饰器返回与给定指令、组件或模板引用选择器匹配的第一个元素。
如果您想要跟随本教程进行操作:
本教程已经验证过可以在 @angular/core v13.0.2 和 @angular/cli v13.0.3 下使用。
ViewChild 使得访问指令成为可能。
假设您有一个 SharkDirective。该指令将查找具有属性 appShark 的元素,并在元素的文本前面添加单词 "Shark"。
理想情况下,您将使用 @angular/cli 来 generate 您的指令:
ng generate directive shark --skip-tests
此命令将创建一个 shark.directive.ts 文件,并将该指令添加到 app.module.ts:
import { SharkDirective } from './shark.directive'; ... @NgModule({ declarations: [ AppComponent, SharkDirective ], ... })
然后,使用 ElementRef 和 Renderer2 来重写文本。将 shark.directive.ts 的内容替换为以下内容:
import { Directive, ElementRef, Renderer2 } from '@angular/core'; @Directive( { selector: '[appShark]' } ) export class SharkDirective { creature = 'Dolphin'; constructor(elem: ElementRef, renderer: Renderer2) { let shark = renderer.createText('Shark '); renderer.appendChild(elem.nativeElement, shark); } }
接下来,在组件模板中的一个包含文本的 span 中添加一个 appShark 属性。将 app.component.html 的内容替换为以下内容:
Fin!
在浏览器中查看应用程序时,将在元素的内容之前呈现单词 "Shark":
Shark Fin!
现在,您还可以访问 SharkDirective 的 creature 实例变量,并使用其值设置一个 extraCreature 实例变量。将 app.component.ts 的内容替换为以下内容:
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { SharkDirective } from './shark.directive'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements AfterViewInit { extraCreature!: string; @ViewChild(SharkDirective) set appShark(directive: SharkDirective) { this.extraCreature = directive.creature; }; ngAfterViewInit() { console.log(this.extraCreature); // Dolphin } }
此代码使用了一个 setter 来设置 extraCreature 变量。请注意,它等待 AfterViewInit 生命周期钩子来访问变量,因为这是子组件和指令可用的时候。
在浏览器中查看应用程序时,您仍将看到 "Shark Fin!" 消息。但是,在控制台日志中,它将显示:
Dolphin
父组件能够访问指令的值。
ViewChild 使得访问具有模板引用变量的本机 DOM 元素成为可能。
假设您在模板中有一个带有 #someInput 引用变量的 。将 app.component.html 的内容替换为以下内容:
现在,您可以使用 ViewChild 访问 并设置 value。将 app.component.ts 的内容替换为以下内容:
import { Component, ViewChild, AfterViewInit, ElementRef } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements AfterViewInit { @ViewChild('someInput') someInput!: ElementRef; ngAfterViewInit() { this.someInput.nativeElement.value = 'Whale!'; } }
当 ngAfterViewInit 触发时, 的值将被设置为:
Whale!
父组件能够设置子 DOM 元素的值。
ViewChild 使得访问子组件并调用子组件可用的方法或访问实例变量成为可能。
假设您有一个 PupComponent。
理想情况下,您将使用 @angular/cli 来 generate 您的组件:
ng generate component pup --flat --skip-tests
此命令将创建 pup.component.ts、pup.component.css 和 pup.component.html 文件。并将该组件添加到 app.module.ts:
import { PupComponent } from './pup.component'; ... @NgModule({ declarations: [ AppComponent, PupComponent ], ... })
然后,在 PupComponent 中添加一个返回消息的 whoAmI 方法:
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-pup', templateUrl: './pup.component.html', styleUrs: ['./pup/component.css'] }) export class PupComponent implements OnInit { constructor() { } whoAmI() { return 'I am a pup component!'; } ngOnInit(): void { } }
接下来,在应用程序模板中引用子组件。将 app.component.html 的内容替换为以下内容:
pup works!
现在,您可以使用 ViewChild 在父组件类中调用 whoAmI 方法。将 app.component.ts 的内容替换为以下内容:
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { PupComponent } from './pup.component'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent implements AfterViewInit { @ViewChild(PupComponent) pup!: PupComponent; ngAfterViewInit() { console.log(this.pup.whoAmI()); // I am a pup component! } }
在浏览器中查看应用程序时,控制台日志将显示:
I am a pup component!
父组件能够调用子组件的 whoAmI 方法。
在本教程中,您使用了 ViewChild 来从父组件类中访问指令、子组件和 DOM 元素。
如果引用动态更改为新元素,ViewChild 将自动更新其引用。
在需要访问多个子元素的情况下,您应该使用 ViewChildren。
如果您想了解更多关于 Angular 的知识,请查看我们的 Angular 专题页面,了解练习和编程项目。