javascript - 为什么当数组元素相同时,Splice 只删除最后一个元素
问题描述
转到此StackBlitz 链接( Not Working
)
转到此StackBlitz 链接( Working Fine
)
我的问题是关于Array.splice
. Array.splice 在数组数据不同但数组数据相同时工作正常,Array.splice
仅删除最后一个索引。在这种情况下,拼接忽略提供的索引以从数组中删除元素。
两个例子都有共同的 HTML 模板
<div class="container">
<table class="table table-dark table-striped table-hover">
<thead>
<tr>
<td scope="col"> Index </td>
<td scope="col"> Value </td>
<td scope="col"> Action </td>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of rows; let i = index" [@itemAnim]>
<td> {{i}} </td>
<td>{{row}}</td>
<td><button class="btn btn-danger" (click)="deleteRow(i)">Delete</button></td>
</tr>
</tbody>
</table>
<button class="btn btn-primary " (click)="addRow()">Add row</button>
</div>
请参阅此示例按预期工作:
index = 1;
rows = [1];
addRow() {
this.rows.length > 0 ? this.index ++ : this.index = 1;
this.rows.push(this.index)
}
deleteRow(row: number) {
return this.rows.length > 0 ? this.rows.splice(row, 1) : this.index = 1;
}
这不起作用:
rows = [1];
addRow() {
this.rows.push(1)
}
deleteRow(row: number) {
this.rows.splice(row, 1) ;
}
在上面的代码中,我只1
在addButton
单击时才推送。并且删除按钮仅从最后一个索引中删除,而不是提供行号索引。
我的问题是为什么会这样?上面的 stackBlitz 链接显示了同样的歧义。
解决方案
因为您实际上是在删除选定的索引,但 Angular 并没有任何关于值之间差异的信息,我们来看一个示例:
我们有这个数组:[1, 1, 1, 1]
并且您删除了第二个项目,然后删除之前的 angular 将看到:
[1, 1, 1, 1]
之后:
[1, 1, 1]
此时 angular 只知道少了一项,但不知道希望项,然后 angular 只删除最后一项。
您需要确保传递不同的值或引用(推荐),然后 Angular 将知道如何区分数组项。
您可以通过使用像这样的对象来修复它:{ data: 1 }
,您的数组将看起来:
[
{ data: 1 },
{ data: 1 },
{ data: 1 },
{ data: 1 }
]
为什么这会奏效?因为引用不一样(值与引用类型),即使数据相同,角度也会看到不同的引用。
这将为您工作:
rows = [{ data: 1 }];
addRow() {
this.rows.push({ data: 1 });
}
deleteRow(row: number) {
this.rows.splice(row, 1);
}
在这个例子中,你总是传递一个带有自己引用的新对象。
这另一个例子不起作用
sameReference = { data: 1 };
rows = [this.sameReference];
addRow() {
this.rows.push(this.sameReference);
}
deleteRow(row: number) {
this.rows.splice(row, 1);
}
因为sameReference
变量存储的是引用,而不是对象,并且 angular 不会(再次)知道项目之间的差异,另外,当您更改一个元素的数据值时,所有元素都会获得该值,因为只有一个对象被引用 N 次数组内。
这也可以
sameReference = { data: 1 };
rows = [{ ...this.sameReference }];
addRow() {
this.rows.push({ ...this.sameReference });
}
deleteRow(row: number) {
this.rows.splice(row, 1);
}
因为在这里我们将对象的值复制到具有不同引用的新对象中。
推荐阅读
- fonts - 如何管理一个字形的多个版本?
- json - 如何在 Scala 的 JSON 测试中屏蔽敏感字段,如密码?
- tcpdf - 在 TCPDF 中嵌入字体
- c++ - 如何使用 gcovr 和多个源/对象目录创建覆盖率报告?
- vb.net - 为什么设置数据源后我的 datagridview 没有被填充?
- r - 在 r 的一个页面中绘制多个 ggplots 对象
- php - 试图循环遍历 PHP 中的数组。有一个更好的方法吗?
- kubernetes - 网真失败,说我的命名空间不存在,指点我的k8s上下文有问题
- swift - Swift:在 Firebase 上更改用户的密码
- spring - Kafka Consumer 在 Spring Boot 中没有收到消息