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

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

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

问题是传递给函数的 newVal是整个数组。有没有办法,我只能得到三角洲的部分?比如说 补充或者 被移除了元素?

52983 次浏览

据我所知没有。想知道我是做什么的吗?我使用前面的一个变量来保存这个值,称为 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,那么您可能知道添加了哪个项目。只要浏览数组的最后一项或第一项,就可以看到了。

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

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

但它确实很乏味,而且这种模式在我的代码中重复出现

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

它具有添加项时的添加值,以及删除项时的删除值。

在 KnockoutJS 3.0中,ko.Observer ableArray 上有一个 订阅选项

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

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

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

对于您的具体问题,您希望获得有关新项或已删除项的通知。要使用 Knokout 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()的类似模式。