15

我需要弄清楚从我的 Knockout observableArray 中删除了哪个元素。请看我的jsFiddle

我可以订阅更改,但它只返回值,即添加或删除后的当前数组。

self.selectedDataPointOptions.subscribe(function(value) {
  // how can I see which one was added or removed?
  alert(value);
});
4

3 回答 3

24

Knockout 包括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/

于 2012-08-28T20:32:07.243 回答
6

提议的解决方案很酷,并且有效,但它涉及每次发生更改时克隆数组,然后进行比较,这可能是 O(n^2)。

这是另一个解决方案:这意味着包含另一个 js 文件......但如果你想要更好的性能,这将提供它:

https://github.com/bobwold/betterObservableArray

这个 observableArray 的替代品(它基本上只是 observable 数组的一个克隆,带有一些额外的代码)使用了淘汰订阅框架,并添加了“添加”和“删除”订阅。

样品用法:

var presidents = ko.betterObservableArray();
presidents.subscribe(presidentAdded, this, "add");
presidents.subscribe(this.presidentRemoved, this, "remove");

...

function presidentAdded(president) {
};

function presidentRemoved (president) {
};

...

于 2013-07-04T00:07:25.123 回答
1

Michael Best 的解决方案 (subscribeArrayChanged) 对我也很有效。但是我需要从 typescript 中使用它,因此我在与原始 'knockout.d.ts' 不同的源中编写了一个小定义源 (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');
    }
); 
于 2013-07-16T15:46:10.313 回答