Подписаться на observable array только для новой или удаленной записи
Так что да, я могу подписаться на заметный массив:
vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});
проблема newVal
передан функции весь массив. В любом случае, я могу получить только часть delta? Скажи добавил или удалены элемент?
6 ответов
по состоянию на KnockoutJS 3.0, есть опция подписки arrayChange on ko.observableArray.
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
или . Просто просмотрите последний элемент массива и первый и вуаля.
попробовать vm.myArray().arrayChanged.subscribe(function(eventArgs))
имеет добавленное значение при добавлении элемента и удаленное значение при удалении элемента.