仅为新的或删除的条目订阅可观察数组

Gel*_*Luo 74 javascript knockout-2.0 knockout.js

所以是的,我可以订阅一个可观察的数组:

vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});
Run Code Online (Sandbox Code Playgroud)

问题是newVal传递给函数的是整个数组.无论如何我只能得到三角洲部分?说添加删除的元素?

Jud*_*ngo 122

从KnockoutJS 3.0开始,ko.observableArray上有一个arrayChange订阅选项.

var myArray = ko.observableArray(["Alpha", "Beta", "Gamma"]);

myArray.subscribe(function(changes) {

    // For this example, we'll just print out the change info
    console.log(changes);

}, null, "arrayChange");

myArray.push("newitem!");
Run Code Online (Sandbox Code Playgroud)

在上面的回调中,changes参数将是一个更改对象数组,如下所示:

[ 
   { 
      index: 3, 
      status: 'added', 
      value: 'newitem!' 
   }
]
Run Code Online (Sandbox Code Playgroud)

对于您的特定问题,您希望收到有关新项目或已删除项目的通知.要使用Knockout 3实现它,它看起来像这样:

myArray.subscribe(function(changes) {

    changes.forEach(function(change) {
        if (change.status === 'added' || change.status === 'deleted') {
            console.log("Added or removed! The added/removed element is:", change.value);
        }
    });

}, null, "arrayChange");
Run Code Online (Sandbox Code Playgroud)

  • 文档表明移动项目也会发出添加或删除的更改信号`myArray.reverse(); // [{index:0,移动:1,状态:'已删除',值:'Alpha'},{index:1,已移动:0,状态:'已添加',值:'Alpha'}]`也许存在应该检查添加和删除状态没有移动属性? (4认同)
  • 如果你问的是,如果单个项目被更改,通知是什么,数组中的一个项目,答案是无.您只会收到删除和添加的通知. (2认同)

MPa*_*lak 7

由于我在其他地方找不到任何相关信息,我将添加一个关于如何使用TypeScript的回复.

这里的关键是使用KnockoutArrayChange接口作为订阅的TEvent.如果你不这样做,它会尝试使用另一个(非泛型)订阅,并会抱怨状态,索引和值不存在.

class ZoneDefinition {
    Name: KnockoutObservable<String>;
}

class DefinitionContainer
{
    ZoneDefinitions: KnockoutObservableArray<ZoneDefinition>;
    constructor(zoneDefinitions?: ZoneDefinition[]){
        this.ZoneDefinitions = ko.observableArray(zoneDefinitions);
        // you'll get an error if you don't use the generic version of subscribe
        // and you need to use the KnockoutArrayChange<T> interface as T
        this.ZoneDefinitions.subscribe<KnockoutArrayChange<ZoneDefinition>[]>(function (changes) {
            changes.forEach(function (change) {
                if (change.status === 'added') {
                    // do something with the added value
                    // can use change.value to get the added item
                    // or change.index to get the index of where it was added
                } else if (change.status === 'deleted') {
                    // do something with the deleted value
                    // can use change.value to get the deleted item
                    // or change.index to get the index of where it was before deletion
                }
            });
        }, null, "arrayChange");
}
Run Code Online (Sandbox Code Playgroud)