从指令创建组件实例时如何等待 ngAfterViewInit() 运行?

Posted

技术标签:

【中文标题】从指令创建组件实例时如何等待 ngAfterViewInit() 运行?【英文标题】:How to wait that ngAfterViewInit() runs while creating instance of a component from a directive? 【发布时间】:2017-09-24 22:12:54 【问题描述】:

我有一个指令在代码中创建一个他使用的组件模板实例并设置它的innerhtml,这将改变模板维度:

  var factory = this.resolver.resolveComponentFactory(MyComponentTemplate);
  this.templateComponent = this.viewContainerRef.createComponent(factory);

  this.templateComponent.instance.htmlStr = anyText;

现在,问题来了。在这个阶段,我将不确定组件的大小:

console.log(this.templateComponent.instance.width);    //undefined
console.log(this.templateComponent.instance.height);   //undefined

在调试中我注意到只有在我的组件运行 ngAfterViewInit() 之后,我才能从我的指令中读取组件模板的宽度和高度并使用这些值。

有没有办法让我的指令等到 ngAfterViewInit() 结束, 而不是用我正在寻找的信息从我的指令中做我需要的事情。

【问题讨论】:

为什么需要在ngAfterViewInit 中?为什么不把它放在this.createComponent() 之后呢?您可能需要先注入ChangeDetectorRef 并调用cdRef.detectChanges() 你完全正确。调用 detectChanges 后它起作用了。非常感谢,你为我节省了很多麻烦 【参考方案1】:
constructor(private cdRef:ChangeDetectorRef) 

...

  var factory = this.resolver.resolveComponentFactory(MyComponentTemplate);
  this.templateComponent = this.viewContainerRef.createComponent(factory);
  this.templateComponent.instance.htmlStr = anyText;

  this.cdRef.detectChanges(); // run change detection immediately

  console.log(this.templateComponent.instance.width);    //undefined
  console.log(this.templateComponent.instance.height);   //undefined

【讨论】:

【参考方案2】:

使用全局注入的ChangeDetectorRef 不是必需的,并且可能不起作用。你可以依赖ComponentRefchangeDetectorRef方法:

var factory = this.resolver.resolveComponentFactory(MyComponentTemplate);
this.templateComponent = this.viewContainerRef.createComponent(factory);
this.templateComponent.instance.htmlStr = anyText;

this.templateComponent.changeDetectorRef.detectChanges();

【讨论】:

以上是关于从指令创建组件实例时如何等待 ngAfterViewInit() 运行?的主要内容,如果未能解决你的问题,请参考以下文章

Angular如何将数据从指令传递到父组件

从指令访问外部组件实例

如何在另一个组件中获取指令/组件实例?

从组件调用的 angular 4 指令的多个实例弄乱了输入值

如何等待从 Vuex 上传的数据?

如何使用组件范围实例层次结构从 C++ 创建 QML 组件