首页 > 解决方案 > TemplateRef 和更改检测

问题描述

最近我开始积极使用模板来定制我的 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>

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

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

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

标签: javascriptangularangular5

解决方案


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

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

在那个指令中,我注入了TemplateRefand ChangeDetectorRef。这种方式不是提供TemplateRef给我需要该模板的地方,而是提供ViewChild(MyDirective)myDirective.template用作模板并调用该组件markForCheck()上的更改检测器。ngAfterViewChecked()


推荐阅读