detectChanges()在Angular的对象数组中没有被触发



*ngFor使我的应用程序非常慢,因为迭代了数千行。除了性能较慢外,它的工作与预期一样。如果选择值或输入值被更改,其值将显示为红色。如果_main。滚动是迭代的,我可以获取所有修改的值,并将它们发送给API进行更新。

<tr *ngFor="let student of _main.students">  <!-- up to 250 students (rows). -->
<ng-container *ngFor="let date of _main.attendance_dates"> <!-- up to 5 school days (rows) in the same week. -->
<ng-container *ngFor="let roll of _main.rolls"> <!-- up to 5 days (rows) times 250 students per two columns (5*250*2) in the same week. -->
<ng-container *ngIf="student.id == roll.student_id && date.date == roll.date">
<td [ngClass] = "roll.email_sent_datetime?'table-cell-attendance-code-emailed' : 'table-cell-attendance-code'">                
<select [(ngModel)]="roll.attendance_type_seq_new" [ngClass]="roll.attendance_type_seq == roll.attendance_type_seq_new ? 'select-attendance-type' : 'select-attendance-type-changed'">            
<option [value]="0" >Not selected</option>
<option *ngFor="let answer of _main.attendance_tyes" [value]="answer.seq">
{{answer.description}}
</option>
</select>

</td>
<td [ngClass] = "roll.email_sent_datetime?'table-cell-attendance-note-emailed' : 'table-cell-attendance-note'">                                        
<input [(ngModel)]="roll.attendance_note_new" placeholder="" title="{{roll.attendance_note_new}}"  [ngClass]="roll.attendance_note == roll.attendance_note_new ? 'input-attendance-note' : 'input-attendance-note-changed'"/>                                                                                                     
</td>   

</ng-container>    
</ng-container>    
</ng-container>    
</tr>         

*我做了一些改变。首先查找索引并显示该项。它足够快,但不会存储更改。我只能通过_main修改一个项目。卷数组。并不是对所有值都触发detectChages()。还有另一个问题。如果选择或输入的值被改变,该值仍以黑色显示,而不是红色。

<tr *ngFor="let student of _main.students">  <!-- up to 250 students (rows). -->
<ng-container *ngFor="let date of _main.attendance_dates"> <!-- up to 5 school days (rows) in the same week. -->
{{getRollSelectedIndex(student.id, date.date)}} <!-- fetch the index of the row in the rolls. -->
<!-- <ng-container *ngFor="let roll of _main.rolls"> up to 5 days (rows) times 250 students per two columns (5*250*2) in the same week. -->
<ng-container *ngIf="_index">
<td [ngClass] = "_main.rolls[_index].email_sent_datetime?'table-cell-attendance-code-emailed' : 'table-cell-attendance-code'">                
<select [(ngModel)]="_main.rolls[_index].attendance_type_seq_new" [ngClass]="_main.rolls[_index].attendance_type_seq == _main.rolls[_index].attendance_type_seq_new ? 'select-attendance-type' : 'select-attendance-type-changed'">            
<option [value]="0" >Not selected</option>
<option *ngFor="let answer of _main.attendance_tyes" [value]="answer.seq">
{{answer.description}}
</option>
</select>

</td>
<td [ngClass] = "_main.rolls[_index].email_sent_datetime?'table-cell-attendance-note-emailed' : 'table-cell-attendance-note'">                                        
<input [(ngModel)]="_main.rolls[_index].attendance_note_new" placeholder="" title="{{_main.rolls[_index].attendance_note_new}}"  [ngClass]="_main.rolls[_index].attendance_note == _main.rolls[_index].attendance_note_new ? 'input-attendance-note' : 'input-attendance-note-changed'"/>                                                                                                     
</td>   

</ng-container>    
<!-- </ng-container>     -->
</ng-container>    
</tr>         

在。ts文件中

getRollSelectedIndex(student_id: number, date: Date){
if (this._main.rolls != null )
{
this._index = this._main.rolls.findIndex(x=>x.student_id === student_id && x.attendance_date === date)
}
}

我不是一个有经验的Angular程序员。我的方法可能是错误的,是否有更好的方法来解决代码中的性能问题?

是的,有更好的方法。您的两个解决方案都需要嵌套迭代,您可以通过在rolls上迭代并创建一个对象来避免这种情况,其中键是学生id,值是roll。对象为您提供了即时访问,因此您不必在模板中遍历它。你可以这样做来构建这个'map':

studentRollsMap = {};
this._main.rolls.forEach(roll => {
studentRollsMap[roll.student_id] = roll;
})

然后在你的模板中,你可以迭代students,同时能够绑定到studentRollsMap[student.id]

根据您的注释,这应该可以将性能提高5到10倍

我能感觉到你现在的紧张,我希望我的话能对你找到最好的解决办法有所帮助。

我认为作为一个好的解决方案,是在类文件中而不是在模板文件中做所有的条件反射样式类。使用.map()迭代数据数组,并为数组中的每个对象添加两个新属性,一个用于<td>roll.email_sent_datetime?'table-cell-attendance-code-emailed' : 'table-cell-attendance-code'",另一个用于<input>样式类_main.rolls[_index].email_sent_datetime?'table-cell-attendance-note-emailed' : 'table-cell-attendance-note'"

我相信使用这种方式将把调整样式所花费的时间缩短到零,并且将是可触摸的。

甚至,您可以遍历整个可靠的数据数组_main.students_main.attendance_dates_main.rolls,以便在*ngFor=""[也在类.ts文件中]中只使用一个数据数组

最新更新