Javascript 订阅仅用于新条目或已删除条目的 observable 数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14149551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 15:50:53  来源:igfitidea点击:

Subscribe to observable array for new or removed entry only

javascriptknockout.jsknockout-2.0

提问by Gelin Luo

So yes I can subscribe to an observable array:

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

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

The problem is the newValpassed to the function is the entire array. Is there anyway I can get only the delta part? Say the addedor removedelement?

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

回答by Judah Gabriel Himango

As of KnockoutJS 3.0, there's an arrayChange subscription optionon ko.observableArray.

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

In the above callback, the changes argument will be an array of change objects like this:

在上面的回调中,changes 参数将是一个像这样的 change 对象数组:

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

For your specific problem, you want to be notified of new or removed items. To implement that using Knockout 3, it'd look like this:

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

回答by MPavlak

Since I couldn't find any info on this elsewhere, I'll add a reply for how to use this with TypeScript.

由于我在其他地方找不到关于此的任何信息,因此我将添加有关如何在 TypeScript 中使用它的回复。

The key here was to use the KnockoutArrayChange interface as TEvent for subscribe. If you don't do that, it'll try to use the other (non-generic) subscribe and will complain about status, index, and value not existing.

这里的关键是使用 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");
}

回答by Hal Noyes

In order to only detect push()and remove()events, and not moving items, I put a wrapper around these observable array functions.

为了只检测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);

The original push function is stored in a closure, then is overlayed with a wrapper that allows me do do anything I want with the pushed item before, or after, it is pushed onto the array.

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

Similar pattern for remove().

的类似模式remove()

回答by Gelin Luo

I am using a similar but different approach, keep track whether an element has been instrumented in the element itself:

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

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();
        }
      })
    }
  });
})

But it is really tedious and the pattern repeated across my code

但这真的很乏味而且模式在我的代码中重复

回答by jjperezaguinaga

None that I know of. Wanna know what I do? I use a previous variable to hold the value, something called selectedItem

我所知道的都没有。想知道我在做什么吗?我使用以前的变量来保存值,称为selectedItem

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

So that way, when something happens to my observable array, I know which item was added.

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

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

This is really verbose, and assuming your array holds many kinds of data, you would need to have some sort of flags that helps you know what to do with your saved variables...

这真的很冗长,假设你的数组包含多种数据,你需要有某种标志来帮助你知道如何处理你保存的变量......

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

An important thing to notice is that you might know which item was added if you know whether pushor unshiftwas used. Just browse the last item of the array or the first one and voila.

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

回答by Rudy

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

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

That has the added value when an item is added, and the removed value when an item is removed.

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