TemplateRef和更改检测

时间:2018-04-30 08:57:19

标签: javascript angular angular5

最近我开始积极使用模板来自定义我的UI组件。我还使用OnPush变化检测策略来优化性能。如果我将模板传递给嵌套组件,一切顺利。用户操作会触发嵌套组件中的更改检测,并且它会一直移动到定义模板的原始组件,并在那里更改检测触发器,更新模板以及我在那里的任何其他逻辑。

但是如果我尝试使用模板制作弹出/警告/工具提示功能 - 我开始将树上的TemplateRef传递给弹出主机组件。因此,如果我对其执行任何操作 - 更改检测将无法到达模板的原点。因此,假设我在伪代码中有这个组件:

<p>Your balance: {{balance}}</p>

<ng-template #popup>
  Your balance: {{balance}}
  <button (click)="balance -= 100">Withdraw</button>
</ng-template>

如果我将此模板传递给位于DOM树中的弹出主机组件:

<main-component>
   <balance></balance>
</main-component>
<popup-host></popup-host>

然后单击“Withdraw”将不会触发原点组件中的更改检测。弹出窗口中模板内的{{balance}}将会更新,但尽管它与原始余额组件中的变量相同 - 余额不会知道此更改,直到某些内容触发了其更改检测。

有人可以分享他们如何解决这个问题吗? OnPush和模板是非常强大的工具,但我无法弄清楚在这种情况下将它们组合在一起的方法,因为TemplateRef没有对其原始组件的任何引用,只有它的DOM注释节点。

我可以强制将原始组件的ChangeDetectorRef传递给弹出服务,但我想提出一个像这样的任意案例的解决方案。任何建议将不胜感激!

1 个答案:

答案 0 :(得分:1)

嗯,我最终做的是创建一个指令:

<ng-template myDirective>
  Content
</ng-template>

在该指令中,我注入了TemplateRefChangeDetectorRef。这样我就不会将TemplateRef提供给我需要该模板的位置,而是ViewChild(MyDirective)并使用myDirective.template作为模板,并在markForCheck()上的变更检测器上调用ngAfterViewChecked()该组件。