将ng-template放在* ngFor内是否会影响性能?

时间:2019-07-02 12:39:50

标签: angular ng-bootstrap angular-template

我们假设以下多次创建的ItemComponent:

<li *ngFor="let item of items">
    <app-item [data]="item"></app-item>
</li>

并包含一些按钮,这些按钮在单击时会显示一些复杂的模态对话框。

当我将对话框的某些ng模板放在ItemComponent内或* ngFor之外时,是否会影响应用程序的性能(例如启动时间或内存占用)?

我的意思是,我知道在调用对话框之前不会实例化模板,但是我不确定模板本身是每个组件创建一次还是每个实例创建一次?

2 个答案:

答案 0 :(得分:1)

  

当我将对话框的某些ng模板放在ItemComponent内或* ngFor之外时,是否会影响应用程序的性能(例如启动时间或内存占用)?

<ng-template>是将要创建的组件。该组件从其内部DOM元素创建模板引用,并且这些DOM元素未呈现在页面上。对于在item中创建的每个ngFor,模板都保留在内存中。 ngTemplate 具有当前的 context 和注入的 context item的值在ngFor内时将出现在当前上下文中,并且在使用ngTemplateOutlet时必须在上下文对象中提供。

使用ngTemplate时,最好将ngFor保留在item之外,并将ngTemplateOutlet作为上下文的一部分传递。

这是一个有助于更好地解释事物的教程。

https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet/

答案 1 :(得分:0)

否,它不会影响您的性能,只会影响分配的内存量。如果您的items.length等于100,并且每个app-item的内部都有一个ng-template-那么将创建100个TemplateRef_实例。

要了解原因,您需要深入研究Angular编译器的功能。

Ivy 进入舞台之前,Angular编译器生成了一个称为“锚定义”的结构。锚定义引用单独编译的“视图定义”(ng-template中的所有内容)。锚定义类型本身在Angular源中不存在,因为锚是现有NodeDef类型(节点定义)的子集。

这样的NodeDef对象的值使Angular在运行时很清楚,这不是需要呈现的常规DOM节点。 checkIndex等于ng-template的-1,因此基本上ng-template与变更检测无关,而且template不等于null(对于a常规DOM节点),但引用了单独编译的ViewDefinition。在运行时,Angular检查nodeDef.element.template! == null并在正确的时间在正确的位置调用createEmbeddedView函数。


Ivy 还将ng-template中的所有内容作为单独的增量DOM指令进行编译。这些说明是在模板函数内部隔离的:

<ng-template>
  <p>Do you see me?</p>
</ng-template>

将被编译为:

function ComponentName_ng_template_0_Template(rf: RenderFlags, ctx: any) {
  if (rf & RenderFlags.Create) {
    // `0` is index
    elementStart(0, 'p');
    // `1` is index
    text(1, 'Do you see me?');
    elementEnd();
  }
}

常春藤也不创建TemplateRef_的任何实例,而是创建一个TView(T代表“模板”),该上下文用作那些指令将被执行。 Ivy比当前的渲染引擎节省更多的内存。


谈论当前的视图引擎-TemplateRef_类的每个实例都具有3个属性-_parentView_defelementRef_parentView引用父组件的NodeDef,在我们的示例中,它是ItemComponentapp-item)的定义。 _defNodeDef函数返回的anchorDef。请注意,将创建100个_def_parentViewelementRef属性。


因此,如果要节省内存,请返回您的问题,最好的选择是在上一级创建一个ng-template并将其作为输入参数传递给组件,例如:

<ng-template #modalTemplate let-data>
  <div class="modal">
    <div class="modal-title">{{ data.title }}</div>
  </div>
</ng-template>

<li *ngFor="let item of items">
  <app-item [data]="item" [modalTemplate]="modalTemplate"></app-item>
</li>

我不知道您的实现,所以这只是一个伪代码:D


  

如果模板本身是每个组件创建一次,还是每个实例创建一次?

在视图引擎中-在每个实例中,在 Ivy 中,它是另一种抽象(但不是按实例创建)。

  

当我将对话框的某些ng模板放在ItemComponent内或* ngFor之外时,是否会影响应用程序的性能(例如启动时间或内存占用)?

我不确定内存占用量是否与应用性能有关related,但是是的-将会分配更多的内存。如果说性能和启动时间-不。如果说的是Chrome(在其他浏览器中不是很了解),那么有一个名为Orinoco的垃圾收集器,它完全参与了内存分配。它可以在3种模式下工作-并行模式,增量模式和并发模式。如果主线程忙于渲染,则V8切换到并发模式。这样做的好处是主线程完全可以自由执行JavaScript和渲染。