そうです、私は監視可能な配列をサブスクライブできます:
vm.myArray = ko.observableArray();
vm.myArray.subscribe(function(newVal){...});
問題はnewVal
、関数に渡されるのが配列全体であるということです。とにかくデルタ部分しか取得できないのですか?追加または削除された要素を言いますか?
そうです、私は監視可能な配列をサブスクライブできます:
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でこれを使用する方法についての返信を追加します。
ここで重要なのは、サブスクライブのTEventとしてKnockoutArrayChangeインターフェイスを使用することでした。そうしないと、他の(一般的ではない)サブスクライブを使用しようとし、ステータス、インデックス、および値が存在しないことについて文句を言います。
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);
元のプッシュ関数はクロージャーに格納され、ラッパーでオーバーレイされます。これにより、配列にプッシュされる前または後に、プッシュされたアイテムでやりたいことが何でもできます。
の同様のパターン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))
これには、アイテムが追加されたときの付加価値と、アイテムが削除されたときの削除された値があります。