Подтвердить что ты не робот

Как заменить данный элемент индекса в knockoutjs

Как вы заменяете данный индекс в наблюдаемом массиве другим элементом.

У меня: ViewModel.Elements()[index]

как я могу заменить его другим элементом.

4b9b3361

Ответ 1

наблюдаемые массивы имеют метод replace. Это занимает старый элемент и новый элемент.

Итак, вы бы назвали это так:

ViewModel.Elements.replace(ViewModel.Elements()[index], yourNewElement);

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

Ответ 2

Немного поздно, но я заметил, что этот вопрос по-прежнему остается без ответа (правильно).

Как утверждали другие, первый ответ не дает ожидаемого поведения, он заменит элемент observableArray на value, а не на index!

Другие ответы чересчур сложны и не используют преимущества новичков.


Чтобы по-настоящему заменить значение в заданном index observableArray, вы должны использовать метод splice().

var myObservable = ko.observableArray([1, 2, 3, 4]);
myObservable.splice(0, 1, 100); // Replace the value at [0] with "100"
myObservable.splice(2, 1, 300); // Replace the value at [2] with "300"
console.log(myObservable()); // [100, 2, 300, 4]

И поскольку метод splice() расширяется нокаутом, он автоматически уведомляет о любых зависимостях, исключая необходимость вызова valueHasMutated().

EDIT/14 февраля 2016 г.

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

var myObservable = ko.observableArray([1, 2, 3, 4]);
var underlyingArray = myObservable();

myObservable.valueWillMutate();

for(...)
   underlyingArray[i] = newValue[i];

this.valueHasMutated();

Ответ 3

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

Вместо того, чтобы нарезать массив и затем склеить массив обратно, я сделал следующее, которое более читаемо ИМХО:

ViewModel.Elements()[index] = yourNewElement;
ViewModel.Elements.valueHasMutated();

Благодаря RP Niemeyer за то, что он показывает, как .replace работает внутри.

Вы также можете расширить observableArray, чтобы поддержать это:

ko.observableArray.fn.replaceIndex = function(index, newValue) {
    this.valueWillMutate();
    this()[index] = newValue;
    this.valueHasMutated();
};

Это означает, что вы можете сделать следующее:

var arr = ko.observableArray([1, 2, 1, 4]);
arr.replaceIndex(2, 3); 
console.log(arr()); // logs [1, 2, 3, 4]

Ответ 4

Вопрос задает вопрос о том, как заменить "данный индекс", а не заданное значение. Принятый ответ работает, когда в наблюдаемом массиве нет повторений, но в случае повторений он не всегда будет вести себя так, как ожидалось. Например. предположим, что:

index = 2;
elements = ko.observableArray([9,8,9]);

а затем мы используем принятый ответ.

elements.replace(elements()[index], 7);

Тогда elements будет [7,8,9] (поскольку replace использует indexOf, который находит самый низкий индекс заданного значения 9), тогда как вопрос, несомненно, ожидает решение, которое сделало бы elements be [9,8,7].

Чтобы по-настоящему заменить на newElement элемент в index в наблюдаемом массиве elements, вы можете использовать следующее.

elements(elements.slice(0, index).concat(newElement, elements.slice(index + 1)));

Что-то более элегантное было бы хорошо. Хотя IIUC это вопрос читаемости, а не производительности.

Ответ 5

Редактирование базового массива и переназначение его сделали трюк для меня. У меня были проблемы с другими подходами.

var underlyingArray = this.someObservableArray();

// Do modifications... Swap some items...
// No one is being notified just yet...

// Reassign to observable to update everything
this.someObservableArray(underlyingArray);