我们假设以下多次创建的ItemComponent:
<li *ngFor="let item of items">
<app-item [data]="item"></app-item>
</li>
并包含一些按钮,这些按钮在单击时会显示一些复杂的模态对话框。
当我将对话框的某些ng模板放在ItemComponent内或* ngFor之外时,是否会影响应用程序的性能(例如启动时间或内存占用)?
我的意思是,我知道在调用对话框之前不会实例化模板,但是我不确定模板本身是每个组件创建一次还是每个实例创建一次?
答案 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
,_def
和elementRef
。 _parentView
引用父组件的NodeDef
,在我们的示例中,它是ItemComponent
(app-item
)的定义。 _def
是NodeDef
函数返回的anchorDef
。请注意,将创建100个_def
,_parentView
和elementRef
属性。
因此,如果要节省内存,请返回您的问题,最好的选择是在上一级创建一个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和渲染。