Определите, какой элемент был добавлен или удален с помощью наблюдаемого объекта 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');
    }
);