如何在Angular中使用ViewChild访问子组件、指令或DOM元素
介绍
本文将向您介绍 Angular 的 ViewChild 装饰器。
在某些情况下,您可能希望从父组件类访问指令、子组件或 DOM 元素。 ViewChild 装饰器返回匹配给定指令、组件或模板引用选择器的第一个元素。
先决条件
如果您想跟随本教程:
- 考虑安装 @angular/cli。
- 使用
@angular/cli创建一个新项目来测试ViewChild的功能。
本教程已使用 @angular/core v13.0.2 和 @angular/cli v13.0.3 进行了验证。
将 ViewChild 与指令一起使用
ViewChild 使访问指令成为可能。
假设你有一个 SharkDirective。 该指令将查找具有属性 appShark 的元素,并在元素中的文本前面加上单词 "Shark"。
理想情况下,您将使用 @angular/cli 到 generate 您的指令:
ng generate directive shark --skip-tests
此命令将创建一个 shark.directive.ts 文件。 并将指令添加到 app.module.ts:
app.module.ts
import { SharkDirective } from './shark.directive';
...
@NgModule({
declarations: [
AppComponent,
SharkDirective
],
...
})
然后,使用 ElementRef 和 Renderer2 重写文本。 将 shark.directive.ts 的内容替换为以下内容:
鲨鱼指令.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);
}
}
接下来,将 appShark 属性添加到组件模板中包含文本的 span 中。 将 app.component.html 的内容替换为以下内容:
app.component.html
<span appShark>Fin!</span>
在浏览器中查看应用程序时,它将在元素内容之前呈现单词 "Shark":
OutputShark Fin!
现在,您还可以访问 SharkDirective 的 creature 实例变量,并使用其值设置一个 extraCreature 实例变量。 将 app.component.ts 的内容替换为以下内容:
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!" 消息。 但是,在控制台日志中,它将显示:
OutputDolphin
父组件能够访问指令中的值。
将 ViewChild 与 DOM 元素一起使用
ViewChild 可以访问具有模板引用变量的本机 DOM 元素。
假设您在模板中有一个 <input> 和 #someInput 引用变量。 将 app.component.html 的内容替换为以下内容:
app.component.html
<input #someInput placeholder="Your favorite sea creature">
现在,您可以使用 ViewChild 访问 <input> 并设置 value。 将 app.component.ts 的内容替换为以下内容:
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 触发时,<input> 的值将设置为:
OutputWhale!
父组件能够设置子 DOM 元素的值。
将 ViewChild 与子组件一起使用
ViewChild 可以访问子组件并调用子组件可用的方法或访问实例变量。
假设你有一个 PupComponent。
理想情况下,您将使用 @angular/cli 到 generate 您的组件:
ng generate component pup --flat --skip-tests
此命令将创建 pup.component.ts、pup.component.css 和 pup.component.html 文件。 并将组件添加到 app.module.ts:
app.module.ts
import { PupComponent } from './pup.component';
...
@NgModule({
declarations: [
AppComponent,
PupComponent
],
...
})
然后,向 PupComponent 添加一个 whoAmI 方法,该方法返回一条消息:
小狗组件.ts
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 的内容替换为以下内容:
app.component.html
<app-pup>pup works!</app-pup>
现在,您可以使用 ViewChild 从父组件类中调用 whoAmI 方法。 将 app.component.ts 的内容替换为以下内容:
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!
}
}
在浏览器中查看应用程序时,控制台日志将显示:
OutputI am a pup component!
父组件能够调用子组件的 whoAmI 方法。
结论
在本教程中,您使用 ViewChild 从父组件类访问指令、子组件和 DOM 元素。
如果引用动态更改为新元素,ViewChild 将自动更新其引用。
如果您想访问多个孩子,您可以使用 ViewChildren 代替。
如果您想了解有关 Angular 的更多信息,请查看 我们的 Angular 主题页面 以获取练习和编程项目。