问题描述
无论我尝试什么,我似乎都无法触发模板内的对象的更改检测,该对象是对象数组中对象数组的一部分。这是(顶部)对象结构:
export interface CompatibleCards {
appid: number,banned: boolean,items: { addedToTrade: boolean,appPosition: number,classid: number,iconUrl: string,marketHashName: string,name: string,numberOfListings: number,position: number,price: number,quantity: number,type: string }[],numberOfCardsInBadge: number,numberOfDifferentCards: number,totalNumberOfItems: number
}
这是模板:
<ng-container *ngIf="this.compatibleCards?.length else no_compatible_cards">
<h3>{{ numberOfCompatibleCards }} cartes compatibles</h3>
<div class="conteneur-ensembles">
<div *ngFor="let currentApp of compatibleCards" class="conteneur-ensemble-compatible">
<h3><a href="https://steamcommunity.com/id/raggart/gamecards/{{ currentApp.appid }}/" target="_blank">{{ currentApp.name }} ({{ currentApp.numberOfDifferentCards }} / {{ currentApp.numberOfCardsInBadge }} cards)</a></h3>
<div class="conteneur-images-cartes">
<span *ngFor="let currentItem of currentApp.items" title="{{ currentItem.name }}" [ngClass]="{ 'conteneur-carte': true,'ajoute-echange': currentItem.addedToTrade }" (click)="ajouterRetirerObjetPourEchange(currentItem,'ajouter')">
<img class="image-carte" src="http://cdn.steamcommunity.com/economy/image/{{ currentItem.iconUrl }}" alt="{{ currentItem.name }}" title="{{ currentItem.addedToTrade }}">
<span *ngIf="currentItem.price && currentItem.price > 0" class="prix-carte" title="{{ currentItem.name }}">{{ currentItem.price / 100 | currency }}</span>
<span *ngIf="currentApp.banned" class="prix-carte" title="{{ currentItem.name }}">--</span>
</span>
</div>
</div>
</div>
</ng-container>
如您所见,我使用 [ngClass]
指令填充基于 CompatibleCards.items 对象的 addedToTrade
属性的 css 类。它正确填充,这意味着如果我在第一次渲染之前更改 addedToTrade
属性,则该类存在。但是,当我稍后尝试使用下面的代码更新对象时,模板不会显示或删除该类。
ajouterRetirerObjetPourEchange(objetAEchanger: any,operation : "ajouter" | "retirer") : void {
console.log(objetAEchanger);
if(operation == "ajouter") {
this.itemsForTrade.push({...objetAEchanger});
} else {
const positionObjetEchangeTrouve = this.itemsForTrade.findindex((currentItem: any) => currentItem.classid == objetAEchanger.classid && currentItem.position == objetAEchanger.position);
this.itemsForTrade.splice(positionObjetEchangeTrouve,1);
}
this.compatibleCards[objetAEchanger.appPosition].items[objetAEchanger.position].addedToTrade = ! this.compatibleCards[objetAEchanger.appPosition].items[objetAEchanger.position].addedToTrade;
// this.compatibleCards[objetAEchanger.appPosition].items = [].concat(this.compatibleCards[objetAEchanger.appPosition].items);
// this.compatibleCards = [].concat(this.compatibleCards);
}
即使使用 [].concat
重新分配数组(或使用扩展 [...this.compatibleCards]
也不会更新模板(请参阅上述函数末尾的注释)。
在更新 items
数组内的对象后,有什么方法可以强制我的模板自行更新吗?
解决方法
第一个解决方案
尝试以编程方式强制检测更改。
在组件的构造函数中使用(通过注入)changeDetectorRef: ChangeDetectorRef
然后在更新表的地方使用 this.changeDetectorRef.detectChanges()
第二种解决方案
如果这不起作用,那么您也可以尝试第二种选择。
您可以声明您的组件具有不同的检测策略 changeDetection:ChangeDetectionStrategy.OnPush
这将应用于组件级别,如
@Component({
selector: 'my-app',template: `some template code`,changeDetection: ChangeDetectionStrategy.OnPush
})
但是请注意,因为这可能会产生副作用。检测策略自上而下起作用。这意味着如果你在你的组件上声明这个策略,它的所有子组件也将遵循这个策略。
同样在这种类型的策略上,Angular 不会检测原始字段的变化。它仅检测引用的更改。
因此,当您执行 this.compatibleCards = [...this.compatibleCards]
时,您更改了该字段的引用,因此必须将其捕获为来自 Angular 的更改。