Почему Splice удаляет только последний элемент, когда элементы массива совпадают - PullRequest
4 голосов
/ 22 февраля 2020

Go к этому StackBlitz Link (Not Working)

Go к этому StackBlitz Link (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 показывает примерно такую ​​же неоднозначность.

1 Ответ

2 голосов
/ 22 февраля 2020

Поскольку вы фактически удаляете выбранный индекс, но Angular не имеет никакой информации о разнице между значениями, давайте рассмотрим пример:

У нас есть этот массив: [1, 1, 1, 1], и вы удалите второй элемент, затем angular перед удалением будет отображаться:

[1, 1, 1, 1]

и после:

[1, 1, 1]

на данный момент angular знает только, что на один пункт меньше, но не знает wi sh item, затем angular просто удаляет последний.

Вам необходимо убедиться, что вы передаете различные значения или ссылки (рекомендуется), тогда angular будет знать, как дифференцировать массив items.

Вы можете исправить это, используя такие объекты, как: { data: 1 }, ваш массив будет выглядеть так:

[
  { data: 1 },
  { data: 1 },
  { data: 1 },
  { data: 1 }
]

И почему это будет работать? потому что ссылки не совпадают ( Значение против типов ссылок ) и angular будет видеть разные ссылки, даже если данные одинаковы.

Это будет работать для вас:

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);
}

, потому что здесь мы копируем значения объекта в новый объект с другой ссылкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...