跳至正文
首页 » 博客 » What Is ViewChild and ContentChild in Angular?

What Is ViewChild and ContentChild in Angular?

(最后更新: 08.09.2023)

Angular中的ViewChild和ContentChild用于组件通信。例如,如果Angular组件的父组件想要访问子组件,则它们使用ViewChild或ContentChild。

在这篇博客文章中,我们将解释Angular ViewChild和Angular ContentChild的本质,并向您展示如何在您的应用程序中使用它们。

主要文章支柱:

什么是ViewChild在Angular

Angular ViewChildViewChildren装饰器用于获取对组件实例,通过使用组件引用名称或类名称。 ViewChild在Angular中返回第一个匹配组件ViewChildren返回所有匹配的组件作为查询列表的项目。我们可以使用这些引用来处理组件类或其DOM元素。

如果要访问父组件中的以下内容,请在Angular中使用 @ ViewChild装饰器。

使用MessageComponent

让我们假设我们有一个MessageComponent,如下面的清单所示:

从 “@ angular/core” 导入 {Component,Input};
@ Component({
选择器: ‘app-message’,
模板: ‘<h2 >{{ message }}</h2>’
})
导出类MessageComponent {
@ Input() message: string;
}

我们在AppComponent中使用MessageComponent,如下所示:

从 “@ angular/core” 导入 {Component,OnInit};
@ Component({
选择器: ‘app-root’,
模板:’
<div>
<h1> 消息 </h1>
<app-message [message]= ‘message’></app-message>
</div>’
})
导出类AppComponent实现OnInit {
信息: 任何;
ngOnInit() {
this.message = ‘Hello World !’;
}
}

MessageComponent将位于AppComponent的模板内。因此,我们可以访问它作为一个ViewChild。

导出类AppComponent实现OnInit,AfterViewInit {
信息: 任何;
@ ViewChild(MessageComponent) messageComponent: MessageComponent;

ngAfterViewInit() {
console.log(this.messageComponent);
}

ngOnInit() {
this.message = ‘Hello World !’;

}
}

更改MessageComponent的值

现在,让我们尝试更改MessageComponent属性的值。

ngAfterViewInit() {
console.log(this.messageComponent);
this.messageComponent.message = ‘Passed as View Child’;
}

在这里,我们正在更改ViewChild属性的值。

使用Angular ViewChildren和QueryList

我们在 * ngFor指令中使用MessageComponent; 因此,有多个对MessageComponent的引用。我们现在可以以ViewChildren和QueryList的形式访问它,如下面的清单所示:

@ ViewChildren(MessageComponent) messageComponent: QueryList<MessageComponent>;
ngAfterViewInit() {
console.log(this.messageComponent);
}

在输出中,您将获得作为ViewChildern的MessageComponent的各种引用。

现在让我们尝试更新ViewChildren的属性,如下面的清单所示:

ngAfterViewInit() {
console.log (此.messageComponent); 此.messageComponent.forEach((item) => { item.message = ‘Infragistics’; });

}

如您所见,我们正在遍历Angular ViewChildren的每个项目并更新每个属性。这将更新属性值,但再次,你会得到错误,“ 表达式已更改后,它是最后一次检查。

您可以通过手动调用更改检测像ViewChild修复它。请记住,我们在AfterContentInit生命周期钩子中没有ViewChildren引用。您将在ngAfterContentInit() 生命周期钩子中获得undefined ,以供ViewChildren参考,如下所示:

ngAfterContentInit() {
console.log(this.messageComponent); // 未定义
}

但是,您可以手动调用更改检测来修复错误: “ 表达式已更改后,它是最后一次检查”

使用变更检测机制

  1. 导入ChangeDetectorRef从 @ angular/core
  2. 注入到构造函数的组件类
  3. 调用detectChanges() 方法后ViewChild属性更改

您可以使用手动更改检测,如下所示:

@ ViewChildren(MessageComponent) messageComponent: QueryList<MessageComponent>;
构造函数 (私有cdr: ChangeDetectorRef) {
}
ngAfterViewInit() {
console.log(this.messageComponent);
this.messageComponent.forEach((item) => { item.message = ‘Infragistics’; });
this.cdr.de tectChanges();
}

什么是ContentChild在角?

Angular ContentChild属性装饰器与ViewChild非常相似,它再次提供了一种强大的方式来与组件中的投影内容进行交互和操作。使用它,您可以轻松地获得DOM中投影内容的引用。

让我们从理解ContentChild开始。位于模板内的任何元素都是ContentChild。

为了理解它,让我们考虑一下MessageContainerComponent。

从 “@ angular/core” 导入 {Component};
@ Component({
选择器: ‘app-messagecontainer’,
模板:’
<div>
<h3 >{{ greetMessage }}</h3>
<ng-content select = “app-message”></ng-content>
</div>’
})
导出类MessageContainerComponent {
greetMessage = ‘点燃UI岩石!’;
}

在这个组件中,我们使用角度内容投影。您可以了解更多关于这里的内容投影

在Angular ContentChild中传递MessageComponent

在 <ng-content> 中投影的任何元素或组件都将成为ContentChild。如果要访问在MessageContainerComponent中投影的MessageComponent并与之通信,则需要将其作为ContentChild读取。

在我们继续学习在Angular中使用ContentChild之前,首先查看如何使用MessageContainerComponent以及如何投影MessageComponent,

从 “@ angular/core” 导入 {Component,OnInit};
@ Component({
选择器: ‘app-root’,
模板:’
<div>
<app-messagecontainer>
<app-message [message]= ‘message’></app-message>
</app-messagecontainer>
</div>’
})
导出类AppComponent实现OnInit {
信息: 任何;
ngOnInit() {
this.message = ‘Hello World !’;
}
}

正如您在上面的清单中看到的,我们在AppComponent中使用MessageContainerComponent,并传递MessageComponent以在其中进行投影。由于MessageComponent在具有内容投影的MessageContainerComponent中使用,因此它成为Angular ContentChild。

由于MessageComponnet被投影并在MessageContainerComponent的模板内使用,因此可以将其用作ContentChild,如下所示:

从 “@ angular/core” 导入 {Component,ContentChild,AfterContentInit};
从 “./message.com组件” 导入 {MessageComponent};

@ Component({
选择器: ‘app-messagecontainer’,
模板:’
<div>
<h3 >{{ greetMessage }}</h3>
<ng-content select = “app-message”></ng-content>
</div>’
})
导出类MessageContainerComponent实现AfterContentInit {
greetMessage = ‘点燃UI岩石!’;
@ ContentChild(MessageComponent)MessageComponentContentChild: MessageComponent;
ngAfterContentInit() {
console.log (此MessageComponentContentChild);
}
}

我们需要做以下工作:

  1. 从 @ angular/core导入ContentChild和AfterContentInit。
  2. 实现组件类的AfterContentInit生命周期挂钩。
  3. 创建一个属性与装饰 @ ContentChild。
  4. 访问ngAfterContentInit生命周期钩子中的内容。

可以在组件的ngAfterContentInit生命周期挂钩内修改ContentChild属性。让我们假设有多个MessageComponent被投影,如下面的清单所示:

从 “@ angular/core” 导入 {Component,OnInit};
@ Component({
选择器: ‘app-root’,
模板:’
<div>
<app-messagecontainer>
<app-message * ngFor = ‘让m个消息’ [message]= ‘m’></app-message>
</app-messagecontainer>
</div>’
})
导出类AppComponent实现OnInit {
消息: 任何;
ngOnInit() {
此.messages = 此.getMessage();
}
getMessage() {
返回 [
“你好印度”
哪支球队赢得了超级碗?’,
“你检查过Ignite UI吗?”,
“带着你破碎的心,让它成为艺术”
];
}
}

现在我们有多个ContentChild,所以我们需要将它们作为ContentChildren来访问,如下面的清单所示:

导出类MessageContainerComponent实现AfterContentInit {
greetMessage = ‘点燃UI岩石!’;
@ ContentChildren(MessageComponent)MessageComponentContentChild: QueryList<MessageComponent>;
ngAfterContentInit() {
console.log (此MessageComponentContentChild);
}
}

使用ContentChildren和QueryList

要使用ContentChildren和QueryList,您需要执行以下任务:

  1. 从 @ angular/core导入ContentChildren、QueryList、AfterContentInit。
  2. 创建一个属性与装饰 @ ContentChildren类型QueryList。
  3. 访问ngAfterContentInit() 生命周期钩子中的ContentChildren引用。

您可以查询ContentChildren中的每个项目,并像这样修改属性:

ngAfterContentInit() {
this. MessageComponentContentChild .forEach((m) => m.message = ‘Foo’);
}

这就是你如何在Angular中使用ContentChildren。

包扎

ViewChild和ContentChild是Angular的两个非常重要的功能。它们用于允许访问父组件中的子组件。作为组件模板一部分的任何指令、组件和元素都将作为ViewChild访问。另一方面,在 <ng-content> 中投影的任何元素或组件都将作为ContentChild访问。

为了进一步简化ViewChild和ContentChild在Angular中,您可以尝试我们的Ignite UI for Angular组件库功能齐全。它提供了f个惊人的角度数据网格和60个高性能图表,使您能够轻松构建现代高性能的角度应用程序。

</p