谁拥有 angular dart 中的 TemplateRef 刷新周期?

Who owns the TemplateRef refreshing cycle in angular dart?

与 ngTemplateOutlet 一起使用时,TemplateRef 刷新周期出现问题。

考虑 HTML:

           <card [value]="item" full>

            <template #buttons let-obj="obj"> <!-- THE TEMPLATE -->
              <button (click)="myBoolean = false"
                *ngIf="myBoolean">  <!-- THIS IF -->
               SET FALSE
              </button>

              <button (click)="myBoolean = true"
                *ngIf="!myBoolean"> <!-- THIS IF --> 
               SET TRUE
              </button>
            </template>

           </card>

           <button (click)="myBoolean = !myBoolean">TOGGLE</button>

所以页面组件有一张卡片。 该卡具有此 属性:

  @ContentChild('buttons')
  TemplateRef buttons; 

此代码使用 TemplateRef 按钮:

<template [ngTemplateOutlet]="buttons"
     [ngTemplateOutletContext]="{ 'obj': value }"></template>

效果不错,按钮是根据页面组件的myBoolean变量显示的。此外,当您单击 <template> 中的按钮时,循环会起作用,并且它们会根据 myBoolean 变量进行更改。

问题是当 myBoolean 变量被 <template> 之外的东西改变时。在上面的 HTML 示例中,当我单击 TOGGLE 按钮时,myBoolean 变量发生变化,但是 <template> 不会相应地刷新。

那么,谁拥有 TemplateRef 的刷新?
我该怎么做才能让它正确刷新?

实例化 TemplateRef 的视图拥有所有权。因为您的组件使用 ChangeDetectionStrategy.OnPush,它们的视图只会在

时更新
  1. 绑定在 组件的视图被触发,
  2. 输入值(例如<card [input]="value">)改变,或者
  3. 组件已注入 ChangeDetectorRef 并调用 changeDetector.markForCheck()

请注意,所有这三个条件都会导致视图被标记为检查;前两个是隐式的,最后一个是显式的。

在您的示例中,您将 <template> 投影到 <card> 组件的视图中。据推测,您的 <card> 组件然后通过 NgTemplateOutlet 在其自己的视图中呈现 <template>。因此,为了在 myBoolean 更改时更新呈现的 <template>,必须将 <card> 组件标记为检查。

单击 <template> 中的按钮时视图正确更新的原因是上述 (1)。事件处理程序将其呈现的视图(<card>)标记为要检查。

同理不起作用当你点击父视图中的TOGGLE按钮时:它只标记要检查的父视图。因此,当由于标记为检查而检测到父视图更改时,将跳过 <card> 视图,因为 <card> 视图满足三个条件中的 none。

因此,为了在单击 TOGGLE 按钮时更新呈现的 <template>,您需要处理程序以某种方式在 ChangeDetectorRef 上调用 markForCheck()呈现 <template> 的视图

好消息是这是可能的,但不幸的是它不是很干净。有多种方法可以实现此目的,但这里有一个想法:

<card>中添加一个方法来抽象使用ChangeDetectorRef的细节:

@Component(...)
class CardComponent {
  CardComponent(this._changeDetector);

  final ChangeDetectorRef _changeDetector;

  void updateButtons() {
    _changeDetector.markForCheck();
  }
}

在页面组件中查询 <card>,并在按下切换时调用更新方法:

@Component(...)
class PageComponent {
  @ViewChild(CardComponent)
  CardComponent card;

  void toggle() {
    myBoolean = !myBoolean;
    card.updateButtons();
  }
}
<button (click)="toggle">TOGGLE</button>

希望这对您有所帮助,干杯!