Как вы заменяете данный индекс в наблюдаемом массиве другим элементом.
У меня:
ViewModel.Elements()[index]
как я могу заменить его другим элементом.
Как вы заменяете данный индекс в наблюдаемом массиве другим элементом.
У меня:
ViewModel.Elements()[index]
как я могу заменить его другим элементом.
наблюдаемые массивы имеют метод replace
. Это занимает старый элемент и новый элемент.
Итак, вы бы назвали это так:
ViewModel.Elements.replace(ViewModel.Elements()[index], yourNewElement);
Внутри это просто устанавливает этот индекс для вашего нового элемента и вызывает valueHasMutated(), чтобы уведомлять потенциальных подписчиков.
Немного поздно, но я заметил, что этот вопрос по-прежнему остается без ответа (правильно).
Как утверждали другие, первый ответ не дает ожидаемого поведения, он заменит элемент 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()
.
Если вам нужно сразу заменить сразу несколько значений, гораздо быстрее получить базовый массив, выполнить замену и затем уведомить изменения.
var myObservable = ko.observableArray([1, 2, 3, 4]);
var underlyingArray = myObservable();
myObservable.valueWillMutate();
for(...)
underlyingArray[i] = newValue[i];
this.valueHasMutated();
Как правильно указывает 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]
Вопрос задает вопрос о том, как заменить "данный индекс", а не заданное значение. Принятый ответ работает, когда в наблюдаемом массиве нет повторений, но в случае повторений он не всегда будет вести себя так, как ожидалось. Например. предположим, что:
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 это вопрос читаемости, а не производительности.
Редактирование базового массива и переназначение его сделали трюк для меня. У меня были проблемы с другими подходами.
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);