角模板通信一个tick延迟



我一直在玩ng-template,发现自己在某种延迟中挣扎。

我在Stackblitz中创建了一个简单的示例。https://stackblitz.com/edit/angular-template-series-v?file = pparent/parent1.component.ts

a parent 组件通过模板将 hello 组件发送到其 child 通过模板。

这个想法是从儿童使用 ngif

Hello 组件到达 ngoninit 钩周期时,它会发出输出。父组件抓住此输出并添加消息显示。

但是,当创建组件而不是稍后一个周期时,该消息未显示。在示例中,您需要单击两次按钮"切换内容"才能使消息"创建"显示。

我该如何解决此问题以使消息出现在同一周期中?

这是由于变化检测如何在Angular中起作用。它与使用ng-template没有链接,因为此修改后的Stackblitz显示(使用Grand Child而不使用NG-Template(。

2个有关变更检测的事情:

  • 事件发生后触发(单击,提交,..(,XHR请求或计时器。
  • 它发生在组件树的顶部到底部

基本上,当您单击"切换"按钮时:

  • 触发处理程序(在您的示例中切换showContent的值,但别无其他。hello组件是不是在此阶段创建的(
  • 更改检测启动,始终从上到下开始。
  • Angular首先检查是否需要为父组件更新视图。由于什么都没有改变,因此尚未更新父的视图。
  • 然后,子组件检测其showContentValue是否已更改。这导致创建hello组件。
  • hello组件初始化后,发出了created事件。父组件收到了此事件,并相应地更新了消息的数组。但是目前已经检查了父母的内容,因此Angular不会对父级视图进行修改。

再次单击"切换"按钮时,同一周期再次运行,这次显示了上一个周期中的数组中的消息

这是一个修改的stackblitz示例,其中具有生命周期钩的日志

注意

强迫变更检测再次运行将在这里解决您的问题,但是如果您不是直接从子女到父母的交流,则最好使用共享服务(基于可观察到的(来广播无关组件之间的消息

这是因为您正在打破角变化检测周期。

单击第一个切换按钮后,正在发生的事情:

1-您单击切换

2-区域J,在单击事件中有挂钩的通知(只需放置(

3-区域确保点击事件完成

4-区域将使Angular知道async事件发生了,我们必须检查组件并确保视图(DOM(反映模型(模型/JavaScript世界(。因此change detection将运行,它将检测所有更改并发现模板中有绑定(ng-if(。

5- ngIf变为真后,,请注意,这是到目前为止的同步,创建ng-container并创建templateOutlet并创建您的hello组件。

再次注意:这都是同步。

6-视图已更新,更改检测现已脱离钩子。

7-在您的hello组件内部,您要触发另一个事件,即created,并通知父组件,并且在您的父组件内您突变数组,而Angular并不关心它,因为没有异步事件,您也没有更新任何输入,在变更检测完成后,您刚刚解雇了另一个同步事件。

8-数组现在已更新,但是该视图不是(在父组件中(

9-您再次单击,同样的事件发生,并且角度更新了第一个更改检测运行中的父视图,并且您会看到数组在视图中反射。

证明我是对的:d:

 onTemplateCreated() {
    console.log('Got the event from chil');
   this.template.push('Template created');
    console.log('this.template',this.template);
  }

您会看到,单击后,控制台显示正确的数组,但是视图不是您再次单击的视图。

现在让我们转到我的代码

 onTemplateCreated() {
    console.log('Got the event from chil');
   this.template = [...this.template,'Template created'];
  }

由于我没有突变并且正在更新扭矩,因此Angular现在必须关心此更改,,但是仍然存在问题,Angular的更改检测器已完成,您在运行intouth的情况下更新了模型任何async事件,所以我们遇到麻烦,因为Angular不喜欢在更改检测完成后更新模型,

因此,您将被抛出一个错误,说:

表达changedafterithasbeencheckederror:表达在检查后发生了变化。先前的值

要解决这个问题,首先阅读我的另一篇文章以理解它,其次,您需要告诉Angular,您知道自己在做什么并手动运行更改检测:

  this._cd.detectChanges

或者,您可以使其异步:

onTemplateCreated() {
    console.log('Got the event from chil');
   setTimeout(()=>{
      this.template = [...this.template,'Template created'];
   })
  }

如果您在父级中运行更改eTector-它将首次单击。

这是一个示例:stackblitz

相关内容

  • 没有找到相关文章

最新更新