首页 > 解决方案 > 为什么当数组元素相同时,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) ;
}

在上面的代码中,我只1addButton单击时才推送。并且删除按钮仅从最后一个索引中删除,而不是提供行号索引。

我的问题是为什么会这样?上面的 stackBlitz 链接显示了同样的歧义。

标签: javascriptangulartypescript

解决方案


因为您实际上是在删除选定的索引,但 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);
}

因为在这里我们将对象的值复制到具有不同引用的新对象中。


推荐阅读