@ViewChild returns 未定义

@ViewChild returns undefined

出于某种原因,我的 Angular 5 应用程序中的 @ViewChild 无法正常工作。 我在我的组件中这样定义它:

案例-detail.component.html:

<div class="inner-tab-content" #innerTabContent>
    <!-- // more content here -->
</div>

我在我的控制器中(在构造函数之上)实现了 @ViewChild,如下所示:

案例-detail.component.ts

@ViewChild('innerTabContent') tabContentElement: ElementRef;

我想在组件中访问它: 案例-detail.component.ts

ngAfterViewInit() {
    console.log("scroll top: " + this.tabContentElement.nativeElement);
}

我已经实现了 AfterViewInit 接口。 ngAfterViewInit() 被正确调用。但是,this.tabContentElement 始终是 undefined

非常感谢任何帮助:)

ViewChild() 在最新的 plunker Angular 版本上工作正常,符合您描述的场景。

这个 plunker 中的演示:https://plnkr.co /edit/KzWnkE5Hvp7NUow6YAxy

编辑:这是上述 Plunker 的替代 StackBlitz:https://stackblitz.com/edit/angular-ivy-pzaglm

组件:

ngAfterViewInit() {
    console.log(this.testView); // correctly outputs the element in console, not undefined
}
  • 检查 ElementRef 和 ViewChild 是否从“@angular/core”正确导入

  • 您的元素可能在 AfterViewInit 时根本不存在(例如,如果有 *ngIf(似乎是根据您的意见案例)

在后一种情况下,您可以使用包装器元素和 ViewChildren ,它会在添加新子元素时发出一些事件 - 有关文档的更多信息,请参见此处:https://angular.io/api/core/ViewChildren

请注意,根据这个问题:@ViewChildren does not get updated with dynamically added DOM elements,原生 div 可能存在一些问题,但这可以通过使用包装 div 的新组件来解决,例如。

编辑

或者你也可以使用超时来等待组件被渲染。我必须说我找到了这个解决方案 'dirty',但很高兴它对你有用:)

然而,即使您访问 AfterViewInit 中的子组件,有时 @ViewChild 仍然返回 null。该问题可能是由 *ngIf 或其他指令引起的。

解决方案是使用@ViewChildren代替@ViewChild并订阅组件准备就绪时执行的changes订阅。

例如,如果在父组件ParentComponent中你想访问子组件MyComponent

import { Component, ViewChildren, AfterViewInit, QueryList } from '@angular/core';
import { MyComponent } from './mycomponent.component';

export class ParentComponent implements AfterViewInit
{
  //other code emitted for clarity

  @ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>;

  public ngAfterViewInit(): void
  {
    this.childrenComponent.changes.subscribe((comps: QueryList<MyComponent>) =>
    {
      // Now you can access to the child component
    });
  }
}

这个问题的不同答案有时是,当您访问它时,子组件仍未呈现。对我来说,这是由于 *ngIf,所以子组件仍然不存在。例如,

<div *ngIf="check">
   <app-child-item></app-child-item>
</div>

并且在您的父 .ts 文件中,您尝试在检查设置为 false 时访问 childItem。

为了让这个在我的案例中始终如一地工作,我替换了所有出现的

*ngIf="check"

[style.display]="check ? 'block' : 'none'"

否则,当我的视图首次加载时不存在的 ViewChild 组件可能会保持未定义状态。