如何在 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

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

import { SharkDirective } from './shark.directive';
...
@NgModule({
  declarations: [
    AppComponent,
    SharkDirective
  ],
  ...
})

然后,使用 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);
  }
}

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

<span appShark>Fin!</span>

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

Shark Fin!

现在,您还可以访问 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
  }
}

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

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

Dolphin

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

使用 ViewChild 与 DOM 元素

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

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

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

现在,您可以使用 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 与子组件

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

假设您有一个 PupComponent

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

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

此命令将创建 pup.component.tspup.component.csspup.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 的内容替换为以下内容:

<app-pup>pup works!</app-pup>

现在,您可以使用 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 专题页面,了解练习和编程项目。


目录
相关文章
|
4天前
|
JavaScript
angular之viewChild和viewChildren
angular之viewChild和viewChildren
|
19天前
|
XML JavaScript 前端开发
哇塞!Web 前端惊现 DOM 元素神操作,一场惊心动魄的网页变革,你准备好了吗?
【8月更文挑战第23天】在Web前端开发中,熟练操作DOM元素至关重要。DOM作为一种编程接口,将HTML/XML文档表示为节点树,便于使用JavaScript访问及修改文档内容与结构。
40 0
|
20天前
|
XML JavaScript 测试技术
Web自动化测试框架(基础篇)--HTML页面元素和DOM对象
本文为Web自动化测试入门指南,介绍了HTML页面元素和DOM对象的基础知识,以及如何使用Python中的Selenium WebDriver进行元素定位、操作和等待机制,旨在帮助初学者理解Web自动化测试中的关键概念和操作技巧。
33 1
|
11天前
|
Java 数据库连接 数据库
强强联手!JSF 与 Hibernate 打造高效数据访问层,让你的应用如虎添翼,性能飙升!
【8月更文挑战第31天】本文通过具体示例详细介绍了如何在 JavaServer Faces (JSF) 应用程序中集成 Hibernate,实现数据访问层的最佳实践。首先,创建一个 JSF 项目并在 Eclipse 中配置支持 JSF 的服务器版本。接着,添加 JSF 和 Hibernate 依赖,并配置数据库连接池和 Hibernate 配置文件。然后,定义实体类 `User` 和 DAO 类 `UserDAO` 处理数据库操作。
31 0
|
19天前
|
JavaScript 前端开发 API
前端开发者的救赎:揭秘JQ对象与DOM元素的神秘转换术
【8月更文挑战第23天】在Web前端开发领域,jQuery(简称JQ)作为一款流行的JavaScript库,极大简化了HTML文档遍历、事件处理、动画及Ajax交互等操作。理解和掌握jQuery对象与DOM元素间的转换至关重要。
25 0
|
27天前
|
JavaScript 前端开发
DOM的概念?获取html元素的方法有哪些?
DOM的概念?获取html元素的方法有哪些?
27 0
|
28天前
|
JavaScript 前端开发 API
如何访问 DOM 中的元素
如何访问 DOM 中的元素
16 0
|
28天前
|
索引
Angular 中的 ngFor 指令
Angular 中的 ngFor 指令
30 0
|
16天前
|
机器学习/深度学习 人工智能 达摩院
第一个Angular应用创建问题之在云开发平台上进行Angular应用的日常环境部署如何解决
第一个Angular应用创建问题之在云开发平台上进行Angular应用的日常环境部署如何解决
|
1月前
|
开发框架 前端开发 JavaScript
使用Angular构建大型企业级应用的技术探索
【8月更文挑战第11天】Angular凭借其强大的组件化开发能力、模块化系统、丰富的生态系统和静态类型检查特性,成为了构建大型企业级应用的理想选择。通过设计良好的架构、使用Angular CLI、组件化开发实践、合理利用服务、性能优化以及严格测试和调试等方法,可以高效地构建出高质量、可维护、可扩展的企业级应用。未来,随着Angular技术的不断发展和完善,相信它将在企业级应用开发领域发挥更加重要的作用。