Angular:ngAfterContentInit后变量为何为undefined?
@ContentChild获取内容显示undefined的原因及解决方法
问题场景
尝试通过@ContentChild访问投影内容,实现示例后在ngAfterContentInit钩子中打印this.child时显示undefined,相关代码如下:
app-root 代码
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-parent> <app-child></app-child> </app-parent> ` }) export class AppComponent {}
app-parent 代码
import { AfterContentInit, Component, ContentChild} from '@angular/core'; import { ChildComponent } from './child/child.component'; @Component({ selector: 'app-parent', template: ` <ng-content></ng-content> ` }) export class ParentComponent implements AfterContentInit { @ContentChild('refChild') child: any; ngAfterContentInit() { console.log('ngAfterContentInit'); console.log(this.child); // 输出undefined } }
app-child 代码
import { Component} from '@angular/core'; @Component({ selector: 'app-child', template: ` <div #refChild> <h1>Child headline</h1> <h2>Child subheadline</h2> </div> ` }) export class ChildComponent {}
原因分析
@ContentChild的作用范围是父组件投影进来的直接内容,无法穿透到子组件的内部模板。你在app-child内部模板定义的#refChild属于ChildComponent的私有视图内容,ParentComponent无法直接通过@ContentChild('refChild')获取到这个变量。
解决方法
根据需求分两种场景处理:
场景1:获取投影进来的ChildComponent实例
如果目标是获取app-child组件本身的实例,直接通过组件类型获取:
修改app-parent代码:
import { AfterContentInit, Component, ContentChild} from '@angular/core'; import { ChildComponent } from './child/child.component'; @Component({ selector: 'app-parent', template: ` <ng-content></ng-content> ` }) export class ParentComponent implements AfterContentInit { // 通过组件类型获取投影进来的子组件实例 @ContentChild(ChildComponent) child: ChildComponent; ngAfterContentInit() { console.log('ngAfterContentInit'); console.log(this.child); // 输出ChildComponent实例 } }
场景2:获取ChildComponent内部的#refChild元素
如果需要获取ChildComponent内部的div元素,需要在ChildComponent中暴露该元素:
- 修改
app-child代码,通过@ViewChild获取内部元素并设为公共属性:
import { Component, ViewChild, ElementRef} from '@angular/core'; @Component({ selector: 'app-child', template: ` <div #refChild> <h1>Child headline</h1> <h2>Child subheadline</h2> </div> ` }) export class ChildComponent { // 获取内部模板元素并暴露为公共属性 @ViewChild('refChild') public refChild: ElementRef; }
- 修改
app-parent代码,先获取ChildComponent实例,再访问其内部元素:
import { AfterContentInit, Component, ContentChild} from '@angular/core'; import { ChildComponent } from './child/child.component'; @Component({ selector: 'app-parent', template: ` <ng-content></ng-content> ` }) export class ParentComponent implements AfterContentInit { @ContentChild(ChildComponent) childComponent: ChildComponent; ngAfterContentInit() { console.log('ngAfterContentInit'); console.log(this.childComponent.refChild); // 输出目标div元素的ElementRef } }
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

