您好,我的Angular7应用包含一个父组件timesheet
和一个子组件row
。在此示例中,我希望timesheet
为给定月份(在本例中为May)的每一天生成一个<app-row>
组件。
现在,<app-row>
组件仅由一个<td>
元素组成,该元素带有一个接受数字的input
字段。到目前为止,没有什么花哨的。
时间表组件:
<div *ngFor="let week of splitMonthIntoWeeks(getMonthDays(month))">
<table>
<thead>
<tr>
<th>
Hours:
</th>
</tr>
</thead>
<tbody>
<tr app-row *ngFor="let day of week"></tr>
</tbody>
</table>
</div>
行组件:
<td><input type="number"></td>
这很好用。但是,如果我尝试使用[(ngModel)]
指令将每个行组件的输入元素链接到模型中的属性,则会得到该应用程序的无限重新渲染(您可以在上面的链接中进行复制。首先,它是可以正常工作,您必须将[(ngModel)]
指令添加到行组件,如下所示。
总而言之,此更改提供了无限的重新渲染:
<td><input type="number" [(ngModel)]="hours"></td>
现在,我真的不知道Angular如何管理更改,也许我错过了一些东西,所以任何提示将不胜感激。
答案 0 :(得分:1)
在此处查看解决方案
https://stackblitz.com/edit/angular-cjxqyt
您不应直接在模板中调用函数(splitMonthIntoWeeks
和getMonthDays
),因为它将在每个渲染周期被调用。这意味着将为每个调用生成一个包含新Date
的新数组。 ngFor
的工作原理是检查其值是否与上一个周期完全相同(使用===
)。
如果比较不匹配,ngFor
认为这是一个新对象,因此它将销毁相应的DOM元素并生成一个新的DOM元素。您可以在console.log
组件构造函数中通过RowComponent
看到它。
在比较两个复杂对象时,例如Date
,它会检查该对象是否真的相同(内存中的指针相同),但是在您的情况下,它不是因为该函数不断重新创建一个新对象。
因此,您不必创建每个周期的函数,而可以创建数组并将结果持久保存在局部属性中,并仅在@Input
month
更改时重新计算此数组。为此,您可以使用onChanges
的生命周期,也可以为@Input
使用设置器(例如在我的示例中)。