Определите, какой элемент был добавлен или удален с помощью наблюдаемого объекта Knockoutjs
Мне нужно выяснить, какой элемент был удален из моего нокаута наблюдаемого массива. См. Мой jsFiddle.
Я могу подписаться на изменение, но он возвращает только значение, которое является текущим массивом после добавления или удаления.
self.selectedDataPointOptions.subscribe(function(value) {
// how can I see which one was added or removed?
alert(value);
});
Ответы
Ответ 1
Нокаут включает ko.utils.compareArrays
, который вы можете использовать для сравнения одного массива с другим. Здесь вспомогательная функция, которая уведомляет каждый добавленный или удаленный элемент в массиве:
ko.observableArray.fn.subscribeArrayChanged = function(addCallback, deleteCallback) {
var previousValue = undefined;
this.subscribe(function(_previousValue) {
previousValue = _previousValue.slice(0);
}, undefined, 'beforeChange');
this.subscribe(function(latestValue) {
var editScript = ko.utils.compareArrays(previousValue, latestValue);
for (var i = 0, j = editScript.length; i < j; i++) {
switch (editScript[i].status) {
case "retained":
break;
case "deleted":
if (deleteCallback)
deleteCallback(editScript[i].value);
break;
case "added":
if (addCallback)
addCallback(editScript[i].value);
break;
}
}
previousValue = undefined;
});
};
Здесь он находится в действии: http://jsfiddle.net/mbest/Jq3ru/
Начиная с Knockout 3.0, вы можете использовать событие arrayChange
, чтобы сделать это более легко. Больше информации здесь: http://blog.stevensanderson.com/2013/10/08/knockout-3-0-release-candidate-available/
Ответ 2
Предлагаемое решение классно и работает, но оно включает клонирование массива каждый раз, когда происходит изменение, а затем сравнение, которое, вероятно, O (n ^ 2).
Вот еще одно решение: это означает включение другого js файла... но если вы хотите получить более высокую производительность, это обеспечит его:
https://github.com/bobwold/betterObservableArray
Эта замена для наблюдаемого массива (который в основном представляет собой только клон наблюдаемого массива с некоторым дополнительным кодом) использует рамки подписки на нокаут и добавляет "добавить" и "удалить" подписки.
Пример использования:
var presidents = ko.betterObservableArray();
presidents.subscribe(presidentAdded, this, "add");
presidents.subscribe(this.presidentRemoved, this, "remove");
...
function presidentAdded(president) {
};
function presidentRemoved (president) {
};
...
Ответ 3
Michael Best solution (subscribeArrayChanged) отлично работает и для меня. Но мне нужно использовать его из typescript и по этой причине я написал немного определите источник (d.ts) в другом источнике от оригинального "knockout.d.ts" для удобного использования в typescript исходный код.
пользовательский файл knockoutext.d.ts:
/// <reference path="knockout.d.ts" />
interface KnockoutObservableArray<T> extends KnockoutObservableArrayFunctions<T> {
subscribeArrayChanged(addCallback: (T) => void , deleteCallback: (T) => void );
}
Маленький фрагмент кода кода:
data[0].Properties.subscribeArrayChanged(
(value: Meta.Data.Property) => {
console.log('add callback called');
},
(value: Meta.Data.Property) => {
console.log('delete callback called');
}
);