我有一个父组件,它有两个模板(Stackblitz):

  • 第一个包含一个简单的数据绑定文本

  • 第二个包含更新数据模型的子组件(来自本演示中的 constructorngOnInit

这是父组件模板:

<ng-template [ngIf]="true">
  <div>
    <b>Value from TemplateComponent: </b>{{ dataService.value | async }}
  </div>
</ng-template>

<ng-template [ngIf]="true">
    <template-component></template-component>
</ng-template>

父组件和子组件都是 ChangeDetectionStrategy.OnPush ,这是一项要求 .

问题是从子组件的 ngOnInit (以及之后的那些)开始的数据更新不会被父组件中的更改检测所拾取 . 这会导致演示中的父组件显示:

TemplateComponent的值:构造函数的值

代替

TemplateComponent的值:来自ngOnInit的值

因为CD仅在构造函数阶段获取更新,但不在 ngOnInit 及更高版本中:

export class TemplateComponent implements OnInit {
    public constructor(public readonly dataService: DataService) {
      this.dataService.setValue("value from constructor");
    }

    public ngOnInit(): void {
      // This update is NOT picked up by CD in parent component
      this.dataService.setValue("value from ngOnInit");
    }
}

除了 markForCheck() 的这种方法之外,我还在孩子中尝试了一个简单的 @Output 事件,但它显然不起作用,因为子项是通过 ng-template 创建的,实际上并不是父组件的直接子项 .

有人会想知道什么是最干净的和Angular的 OnPush 友好的方法,用于从 ng-template 创建控件将数据传递给父级?

P.S.:

最干净和Angular的OnPush友好方法

,我的意思是保持所有部分(组件和服务松散耦合)的东西,例如,不涉及 setTimeout() 或其他脏修复 .