简介
本文将向您介绍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
来生成
您的指令:
1ng generate directive shark --skip-tests
此命令将创建一个Shark.Directive.ts
文件。并将指令添加到app.mode.ts
中:
1[label app.module.ts]
2import { SharkDirective } from './shark.directive';
3...
4@NgModule({
5 declarations: [
6 AppComponent,
7 SharkDirective
8 ],
9 ...
10})
然后使用ElementRef
和Renderer2
重写文本。将Shark.Directive.ts
的内容替换为:
1[label shark.directive.ts]
2import {
3 Directive,
4 ElementRef,
5 Renderer2
6} from '@angular/core';
7
8@Directive(
9 { selector: '[appShark]' }
10)
11export class SharkDirective {
12 creature = 'Dolphin';
13
14 constructor(elem: ElementRef, renderer: Renderer2) {
15 let shark = renderer.createText('Shark ');
16 renderer.appendChild(elem.nativeElement, shark);
17 }
18}
接下来,在组件模板中包含文本的span
中添加一个appShark
属性。将app.Component.html
的内容替换为:
1[label app.component.html]
2<span appShark>Fin!</span>
在浏览器中查看应用程序时,它会在元素内容之前呈现单词Shark
:
1[secondary_label Output]
2Shark Fin!
现在,您还可以访问SharkDirective
的creature
实例变量,并使用其值设置extraCreature
实例变量。将app.component.ts
的内容替换为以下内容:
1[label app.component.ts]
2import {
3 Component,
4 ViewChild,
5 AfterViewInit
6} from '@angular/core';
7import { SharkDirective } from './shark.directive';
8
9@Component({
10 selector: 'app-root',
11 templateUrl: './app.component.html',
12 styleUrls: ['./app.component.css']
13})
14export class AppComponent implements AfterViewInit {
15 extraCreature!: string;
16
17 @ViewChild(SharkDirective)
18 set appShark(directive: SharkDirective) {
19 this.extraCreature = directive.creature;
20 };
21
22 ngAfterViewInit() {
23 console.log(this.extraCreature); // Dolphin
24 }
25}
这段代码使用了一个setter来设置Extra Creature
变量。请注意,它等待AfterViewInit
生命周期hook访问变量,因为这是子组件和指令可用的时候。
在浏览器中查看应用程序时,您仍会看到Shark Fin!
消息。但是,在控制台日志中,它将显示:
1[secondary_label Output]
2Dolphin
父组件能够访问指令中的值。
结合使用ViewChild
和DOM元素
通过ViewChild
可以访问具有模板引用变量的原生DOM元素。
假设您的模板中有一个<INPUT>
,引用变量为# ome Input
。将app.Component.html
的内容替换为:
1[label app.component.html]
2<input #someInput placeholder="Your favorite sea creature">
现在,您可以通过ViewChild
访问<input>
,并设置value
。将app.Component.ts
的内容替换为:
1[label app.component.ts]
2import {
3 Component,
4 ViewChild,
5 AfterViewInit,
6 ElementRef
7} from '@angular/core';
8
9@Component({
10 selector: 'app-root',
11 templateUrl: './app.component.html',
12 styleUrls: ['./app.component.css']
13})
14export class AppComponent implements AfterViewInit {
15 @ViewChild('someInput') someInput!: ElementRef;
16 ngAfterViewInit() {
17 this.someInput.nativeElement.value = 'Whale!';
18 }
19}
当ngAfterViewInit
触发时,<input>
的值将被设置为:
1[secondary_label Output]
2Whale!
父组件能够设置子DOM元素的值。
对子组件使用ViewChild
ViewChild
使访问子组件和调用方法或访问子组件可用的实例变量成为可能。
假设您有一个‘PupComponent’。
理想情况下,您可以使用@angular/cli
来生成
您的组件:
1ng generate component pup --flat --skip-tests
该命令将创建pup.Component.ts
、pup.Component.css
和pup.Component.html
文件。并将组件添加到app.mode.ts
中:
1[label app.module.ts]
2import { PupComponent } from './pup.component';
3...
4@NgModule({
5 declarations: [
6 AppComponent,
7 PupComponent
8 ],
9 ...
10})
然后,在PupComponent
中添加一个walAmI
方法,该方法返回一条消息:
1[label pup.component.ts]
2import { Component, OnInit } from '@angular/core';
3
4@Component({
5 selector: 'app-pup',
6 templateUrl: './pup.component.html',
7 styleUrs: ['./pup/component.css']
8})
9export class PupComponent implements OnInit {
10
11 constructor() { }
12
13 whoAmI() {
14 return 'I am a pup component!';
15 }
16
17 ngOnInit(): void {
18 }
19
20}
接下来,引用应用程序模板中的子组件。将app.Component.html
的内容替换为:
1[label app.component.html]
2<app-pup>pup works!</app-pup>
现在,您可以使用ViewChild
从父组件类中调用whAmI
方法。将app.Component.ts
的内容替换为:
1[label app.component.ts]
2import {
3 Component,
4 ViewChild,
5 AfterViewInit
6} from '@angular/core';
7import { PupComponent } from './pup.component';
8
9@Component({
10 selector: 'app-root',
11 templateUrl: './app.component.html',
12 styleUrls: ['./app.component.css'],
13})
14export class AppComponent implements AfterViewInit {
15 @ViewChild(PupComponent) pup!: PupComponent;
16 ngAfterViewInit() {
17 console.log(this.pup.whoAmI()); // I am a pup component!
18 }
19}
在浏览器中查看应用程序时,控制台日志将显示:
1[secondary_label Output]
2I am a pup component!
父组件能够调用子组件的everAmI
方法。
结论
在本教程中,您使用ViewChild
来访问父组件类中的指令、子组件和DOM元素。
如果引用动态更改为新元素,则ViewChild
会自动更新其引用。
如果要访问多个子对象,则应改用ViewChildren
。
如果您想了解更多有关ANGLE的信息,请查看我们的ANGLE主题页面以获取练习和编程项目。