@ViewChild 在 *ngIf 中使用。

19 浏览
0 Comments

@ViewChild 在 *ngIf 中使用。

问题

什么是在相应的元素在模板中被显示后获取@ViewChild最优雅的方式?

以下是一个示例,同样提供了Plunker

Component.template.html:


Component.component.ts:

export class AppComponent {
    display = false;
    @ViewChild('contentPlaceholder', { read: ViewContainerRef }) viewContainerRef;
    show() {
        this.display = true;
        console.log(this.viewContainerRef); // undefined
        setTimeout(() => {
            console.log(this.viewContainerRef); // OK
        }, 1);
    }
}

我有一个组件默认情况下其内容是被隐藏的。当有人调用show()方法时,它就变得可见了。然而,在Angular 2的变更检测完成之前,我不能引用到viewContainerRef。我通常会像上面显示的那样将所有必需的操作打包到setTimeout(()=>{},1)中。是否有更正确的方法呢?

我知道有一个选项ngAfterViewChecked,但它会造成太多无用的调用。

答案(Plunker)

admin 更改状态以发布 2023年5月23日
0
0 Comments

另一种解决方法是手动运行变更检测器。

您首先要注入ChangeDetectorRef

constructor(private changeDetector : ChangeDetectorRef) {}

然后在更新控制*ngIf的变量后调用它。

show() {
        this.display = true;
        this.changeDetector.detectChanges();
    }

0
0 Comments

为ViewChild使用setter:

 private contentPlaceholder: ElementRef;
 @ViewChild('contentPlaceholder') set content(content: ElementRef) {
    if(content) { // initially setter gets called with undefined
        this.contentPlaceholder = content;
    }
 }

一旦*ngIf变为true,setter将被调用一个元素引用。

请注意,对于Angular 8,您必须确保设置{ static: false },这是其他Angular版本中的默认设置:

 @ViewChild('contentPlaceholder', { static: false })

注意:如果contentPlaceholder是一个组件,则可以将ElementRef更改为您的组件类:

  private contentPlaceholder: MyCustomComponent;
  @ViewChild('contentPlaceholder') set content(content: MyCustomComponent) {
     if(content) { // initially setter gets called with undefined
          this.contentPlaceholder = content;
     }
  }

0