繁体   English   中英

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

[英]Subscribe to observable array for new or removed entry only

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

vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});

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

从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!");

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

[ 
   { 
      index: 3, 
      status: 'added', 
      value: 'newitem!' 
   }
]

对于您的特定问题, 您希望收到有关新项目或已删除项目的通知 要使用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");

由于我在其他地方找不到任何相关信息,我将添加一个关于如何使用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");
}

为了只检测push()remove()事件,而不是移动项,我在这些可观察的数组函数周围放了一个包装器。

var trackPush = function(array) {
    var push = array.push;
    return function() {
        console.log(arguments[0]);
        push.apply(this,arguments);
    }
}
var list = ko.observableArray();
list.push = trackPush(list);

原始的push函数存储在一个闭包中,然后用一个包装器覆盖,这个包装允许我在推送到数组之前或之后对推送的项目执行任何我想做的事情。

remove()相似模式。

我正在使用类似但不同的方法,跟踪元素本身是否已检测到元素:

myArray.subscribe(function(array){
  $.each(array, function(id, el) {
    if (!el.instrumented) {
      el.instrumented = true;
      el.displayName = ko.computed(function(){
        var fn = $.trim(el.firstName()), ln = $.trim(el.lastName());
        if (fn || ln) {
          return fn ? (fn + (ln ? " " + ln : "")) : ln;
        } else {
          return el.email();
        }
      })
    }
  });
})

但它真的很乏味,我的代码中重复了这种模式

我不知道。 想知道我在做什么吗? 我使用前一个变量来保存值,称为selectedItem

vm.selectedItem = ko.observable({});
function addToArray(item) { vm.selectedItem(item); vm.myArray.push(item); }

这样,当我的可观察数组发生某些事情时,我知道添加了哪个项目。

vm.myArray.subscribe(function(newArray) { var addedItem = vm.selectedItem(item); ... }

这真的很冗长,假设您的数组包含多种数据,您需要使用某种标志来帮助您了解如何处理已保存的变量...

vm.myArray.subscribe(function(newArray) {
  if ( wasUpdated )
    // do something with selectedItem
  else
    // do whatever you whenever your array is updated
}

需要注意的一件重要事情是,如果您知道是否使用了push或非unshift ,您可能知道添加了哪个项目。 只需浏览数组的最后一项或第一项即可。

试试vm.myArray().arrayChanged.subscribe(function(eventArgs))

添加项目时具有附加值,删除项目时具有删除的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM