Angular6 @ViewChild 未定义与 ngIf

big*_*ull 24 viewchild angular

我在使用 @ViewChild 和通过 ngIf 显示的组件时遇到问题。我找到了各种解决方案,但没有一个对我有用。这是我的主要组件,包括多个步骤(为了简洁起见,我在代码中只显示了 2 个),一个用于向前导航的按钮和一个用于重置第一步返回的组件的按钮。第一步显示在页面打开:

...
<div class="my-container">
    <first-child *ngIf="showFirtChild"></first-child>
    <second-child *ngIf="showSecondChild"></second-child>
</div>
<button (click)="goToNextStep()"></button>
<button (click)="reset()"></button>
...
Run Code Online (Sandbox Code Playgroud)
export class MainComponent implements OnInit {
    @ViewChild(FirstChild) private firstChildComp: MyFirstChildComponent;
    showFirtChild: boolean = true;

    ngOnInit() {
        //here firstChildComp is defined
    }

    //code for navigate through steps
    reset() {
        this.showFirtChild= true;
        this.firstChildComp.fillTable(); //fillTable is a function defined in MyFirstChildComponent
    }
...
}
Run Code Online (Sandbox Code Playgroud)

在步骤导航期间,对 firstChildComp 的引用丢失,并且在调用 reset() 时,childComp 结果未定义。我知道原因是 ngIf,所以我尝试使用 ngAfterViewInit:

ngAfterViewInit() {
    this.fcomp = this.firstChildComp;
}

reset() {
        this.showFirtChild= true;
        this.fcomp .fillTable();
}
Run Code Online (Sandbox Code Playgroud)

但它不能解决我的问题。有什么建议吗?

Edu*_*che 24

正如 Angular 的 Doc 所说:

“在更改检测运行之前解析查询结果是正确的。如果任何查询结果在嵌套视图中(例如 *ngIf),则在更改检测运行后解析查询。”

因此,将参数传递{ static: false }给@ViewChild 可以解决问题,因为它是在 ngAfterViewInit 上{ static: true }访问的,而不是在 ngOnInit 上运行更改检测之前访问。

  • static 选项仅在版本 8+ 中可用(根据 Angular 文档) (5认同)

Fel*_*ues 15

ngIf 将从 DOM 中删除您的组件。所以它变得不确定。如果您[hidden]="!showFirstChild"改为使用,它只会被隐藏,并且将在组件中可用。

这是一个堆栈闪电战,您可以在其中进行检查。


dee*_*Dev 13

尝试在两者之间运行更改检测,以确保 DOM 模板在重置更改后读取 DOM。

在模板中:

<first-child #firstChild *ngIf="showFirtChild"></first-child>
Run Code Online (Sandbox Code Playgroud)

在控制器中:

import { ChangeDetectorRef } from '@angular/core';

export class exampleClass implements 
{

  @ViewChild('firstChild') public firstChildComp: MyFirstChildComponent;
  public fcomp: any;
  public showFirtChild: boolean;

  constructor(private ref: ChangeDetectorRef,
            //your services) {}

  public ngAfterViewInit() 
  {
      this.showFirtChild = true;
      this.ref.detectChanges();

      this.fcomp = this.firstChildComp;
  }

  public reset(): void 
  {
      this.fcomp.fillTable();
  }
}
Run Code Online (Sandbox Code Playgroud)

ChangeDetectorRef 文档以供进一步阅读。