【发布时间】:2019-08-26 21:55:55
【问题描述】:
我现在正在使用 Angular 6。
所以我有一个我想通过 ngFor 显示的对象数组。 从 html 页面,我可以执行 2 种不同的操作 - 向该数组添加一个新项目并从那里删除一个项目。
会发生的情况是,有时添加新项目会导致现有项目从视图表示中消失。
更确切地说,当这种情况发生时,我有一个场景(它也在所附的屏幕截图中描述):
- 添加几个项目,所以我在一个数组中总共有 5 个项目,显示值为 "a","b","c","d",null
- 删除项目“c”,然后删除项目“b”(所以现在我有“a”,“d”,null)
- 设置最后一项的值(现在我有 "a","b","e")
- 添加新项目。这是一个问题开始的地方。项目已添加到数组中,但同时值“d”在此之后不再显示。现在奇怪的是值“d”实际上仍在模型中(屏幕截图上的最后一个日志),但它只是没有显示。
说实话,甚至不知道如何开始调试。
添加新商品代码:
addItem () {
var newItem = new CardItem(String(++this.itemCount), null);
console.log("Created new item: "+JSON.stringify(newItem));
this.testCard.back.push(newItem);
console.log("Items after adding new option: "+JSON.stringify(this.testCard.back));
}
删除项目代码:
removeAnswer (itemIndex: string) {
if (itemIndex!=null) {
var index = this.testCard.back.findIndex(answ => answ.id == itemIndex);
console.log("Index of item to be removed: ["+index+"]. Object to be removed: ["+JSON.stringify(this.testCard.back[index])+"]");
this.testCard.back.splice(index,1);
console.log("Item after removal: "+JSON.stringify(this.testCard.back));
} else {
console.debug("Can't remove item, index is missed. ["+itemIndex+"].");
}
}
<mat-form-field *ngFor="let cardBack of testCard.back; let i = index; let first = first; let last = last">
<input matInput placeholder="Item {{i+1}}" name="item{{i+1}}" [(ngModel)]="cardBack.item" >
<mat-icon matSuffix (click)="removeItem(cardBack.id)">close</mat-icon>
</mat-form-field>
提前谢谢大家!
已添加
我通过将trackBy 添加到我的 NgFor(作为答案添加)来解决了一个问题。但是,我不明白为什么它在一种情况下有效,但在另一种情况下无效。
所以我尝试实现 trackBy 函数。一个有效的只是返回传递给函数的索引值。不起作用的实现是使用唯一的back.id 值,但它并没有以某种方式起作用。我认为对于 trackBy 函数,我们需要一些不会改变的对象的唯一标识符,所以这就是我尝试使用 back.id 的原因——它生成一次,之后就不会改变。
另一方面,在我们从 NgFor 中添加/删除项目之后,$index 的值每次都会改变,因此相同的项目将被不同的 id 跟踪(仍然是唯一的)。
所以在这两种情况下,函数都会返回唯一值。为什么在 trackBy 函数中使用 $index 时它可以工作,但当我尝试使用作为对象一部分的唯一标识符 (back.id) 时它不起作用?
【问题讨论】:
-
我根据您的代码创建了一个 stackblitz,它运行良好。 angular-jwwfnh.stackblitz.io。由于您的共享代码和模板中的方法名称不匹配,因此进行了一些更正。
-
你把默认的
ChangeDetectionStrategy改成onPush了吗? -
@Batajus,不,我没有覆盖它。
-
@ashish.gd,我相信您在项目中使用了 Angular 7。正如我所提到的,我正在使用 Angular 6。我会尝试更新到 Angular 7,并会在此处回复答案。
-
@ashish.gd 我用 Angular 7 尝试过,但令人惊讶的是它对我也不起作用。修复它的方法是添加
trackBy函数,该函数按索引跟踪元素。在修复它之前,我注意到一件奇怪的事情。即使“项目 2”的输入值消失了,它仍然在名为ng-reflect-model的元素属性中正确显示,据我所知,这是出于调试目的,应该显示一个必须由ngModel使用的值。跨度>