当前位置:   article > 正文

如何在 Angular 中使用 ViewChild 来访问子组件、指令或 DOM 元素

如何在 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/cligenerate 您的指令:

ng generate directive shark --skip-tests
  • 1

此命令将创建一个 shark.directive.ts 文件,并将该指令添加到 app.module.ts


import { SharkDirective } from './shark.directive';
...
@NgModule({
  declarations: [
    AppComponent,
    SharkDirective
  ],
  ...
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后,使用 ElementRefRenderer2 来重写文本。将 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);
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

接下来,在组件模板中的一个包含文本的 span 中添加一个 appShark 属性。将 app.component.html 的内容替换为以下内容:


<span appShark>Fin!</span>
  • 1
  • 2

在浏览器中查看应用程序时,将在元素的内容之前呈现单词 "Shark"


Shark Fin!
  • 1
  • 2

现在,您还可以访问 SharkDirectivecreature 实例变量,并使用其值设置一个 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
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

此代码使用了一个 setter 来设置 extraCreature 变量。请注意,它等待 AfterViewInit 生命周期钩子来访问变量,因为这是子组件和指令可用的时候。

在浏览器中查看应用程序时,您仍将看到 "Shark Fin!" 消息。但是,在控制台日志中,它将显示:


Dolphin
  • 1
  • 2

父组件能够访问指令的值。

使用 ViewChild 与 DOM 元素

ViewChild 使得访问具有模板引用变量的本机 DOM 元素成为可能。

假设您在模板中有一个带有 #someInput 引用变量的 <input>。将 app.component.html 的内容替换为以下内容:


<input #someInput placeholder="Your favorite sea creature">
  • 1
  • 2

现在,您可以使用 ViewChild 访问 <input> 并设置 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!';
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

ngAfterViewInit 触发时,<input> 的值将被设置为:


Whale!
  • 1
  • 2

父组件能够设置子 DOM 元素的值。

使用 ViewChild 与子组件

ViewChild 使得访问子组件并调用子组件可用的方法或访问实例变量成为可能。

假设您有一个 PupComponent

理想情况下,您将使用 @angular/cligenerate 您的组件:

ng generate component pup --flat --skip-tests
  • 1

此命令将创建 pup.component.tspup.component.csspup.component.html 文件。并将该组件添加到 app.module.ts


import { PupComponent } from './pup.component';
...
@NgModule({
  declarations: [
    AppComponent,
    PupComponent
  ],
  ...
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

然后,在 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 {
  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

接下来,在应用程序模板中引用子组件。将 app.component.html 的内容替换为以下内容:


<app-pup>pup works!</app-pup>
  • 1
  • 2

现在,您可以使用 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!
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

在浏览器中查看应用程序时,控制台日志将显示:


I am a pup component!
  • 1
  • 2

父组件能够调用子组件的 whoAmI 方法。

结论

在本教程中,您使用了 ViewChild 来从父组件类中访问指令、子组件和 DOM 元素。

如果引用动态更改为新元素,ViewChild 将自动更新其引用。

在需要访问多个子元素的情况下,您应该使用 ViewChildren

如果您想了解更多关于 Angular 的知识,请查看我们的 Angular 专题页面,了解练习和编程项目。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/191906
推荐阅读
相关标签
  

闽ICP备14008679号