データモデル機構のイベント詳細
- DataItemのchangeイベントのイベントオブジェクト
- DataModelのitemsChangeイベントのイベントオブジェクト
- DataModelManagerのitemsChangeイベントオブジェクト
- beginUpdate/endUpdate
- typeで配列指定したプロパティのObservableArray変更時のイベント発生順序
- typeで配列指定したプロパティへの値代入時のイベント発生条件
DataItemのchangeイベントのイベントオブジェクト
DataItemのchangeイベントリスナーの引数に渡されるイベントオブジェクトは以下のような構造になっています。
props: {
変更されたプロパティ1: {
oldValue: (変更前の値),
newValue: (変更後の値)
},
変更されたプロパティ2: {
oldValue: (変更前の値),
newValue: (変更後の値)
}, ...
},
type: 'change',
target: 当該データアイテムインスタンス
}
DataModelのitemsChangeイベントのイベントオブジェクト
itemsChangeイベントオブジェクトは以下のような構造になっています。
※ データアイテムの再生成とは、アップデートセッション中に削除されたアイテムと同じIDを持つアイテムが同セッション中に生成されることです。具体例についてはこの後のbeginUpdate/endUpdateに記述しています。
changed: [(changeイベントオブジェクト配列)],
created: [(データアイテム配列)],
recreated: [
{
id: (再生成されたデータアイテムのID),
newItem: 再生成されたデータアイテムのインスタンス,
oldItem: 削除されたデータアイテムのインスタンス
},
...
],
removed: [(データアイテム配列)],
type: 'itemsChange',
target: 当該データモデルインスタンス
}
recreatedについて
DataModelのitemsChangeイベント中のrecreatedプロパティには、beginUpdate()とendUpdate()の間でremove⇒createされたインスタンスが入ります。
コード例:
var item1 = model.create({
id: '001',
val: 1
});
var item2 = model.create({
id: '002',
val: 2
});
// beginUpdateの呼び出し
manager.beginUpdate();
// item1とitem2を削除
model.remove(['001', '002']);
// idが'001'のアイテムを再生成
var newItem1 = model.create({
id: '001',
val: 44
});
// itemsChangeイベント発生。
// recreated: { id: '001', newItem: (再生成されたDataItemインスタンス), oldItem: (削除されたアイテム) }
manager.endUpdate();
DataModelManagerのitemsChangeイベントオブジェクト
データモデルマネージャのitemsChangeイベントオブジェクトは、以下のような構造です。
models: {
データモデル名1: データモデルのitemsChangeイベントオブジェクト,
データモデル名2: データモデルのitemsChangeイベントオブジェクト,
...
},
target: 当該データモデルマネージャインスタンス,
type: 'itemsChange'
}
beginUpdate/endUpdate
データモデルマネージャのbeginUpdate()、endUpdate()メソッドを使うと、beginUpdate()を呼んでからendUpdate()を呼ぶまでの間のデータアイテムの変更、生成、削除に伴って発生するイベントを、endUpdate()のタイミングまで遅延させることができます。データアイテムが持つObservableArray()のchangeイベントも遅延します。changeBeforeイベントは遅延しません。
また、begin/endUpdateの仕組みを用いると、同一データアイテムに対する複数の変更は1つのchangeイベントにマージされます。
var item1 = model.create({
id: '001',
val: 1
});
var item2 = model.create({
id: '002',
val: 2
});
var item3 = model.create({
id: '003',
val: 3
});
var item4 = model.create({
id: '004',
val: 4
});
// IDが'001'と'002'のデータアイテムにchangeイベントリスナーを登録
model.get('001').addEventListener('change', function(ev){ alert('item1 change!'); });
model.get('002').addEventListener('change', function(ev){ alert('item2 change!'); });
// データモデルのitemsChangeイベントリスナーを登録
model.addEventListener('itemsChange', function(ev){ alert('itemsChange!') });
manager.beginUpdate(); //modelはこのデータモデルマネージャに属しているものとする
item1.set('val', 11); // beginUpdate-endUpdateの間なので、イベントはこの時点では発生しない
// item1.valの値を元に戻す
item1.set('val', 1);
// item2.valの値を変更
item2.set('val', 22);
// item3とitem4を削除
model.remove(['003', '004']);
// idが004のアイテムを再度作成
var newItem4 = model.create({ id: '004', val: 44 });
// idが'005'のアイテムを生成
var item5 = model.create({ id: '005', val: 55 });
// ここまでで、イベントハンドラは一度も実行されない
manager.endUpdate(); // endUpdate()を呼び出すと、イベントがまとめて発生する
// 「item2 change!」⇒「itemsChange!」の順にアラートが表示される
上記の例での、endUpdate()時に実行されるitemsChangeイベントハンドラの引数evは以下のようになります。
changed: [(item2のchangeイベントオブジェクト)],
created: [item5],
recreated: [
{
id: '004',
newItem: newItem4, // createで再作成されたval==44のインスタンス
oldItem: item4 // removeで削除されたval==4のインスタンス
}
],
removed: [item3],
type: 'change',
target: model
}
データモデルのitemsChangeイベントオブジェクトに格納されるアイテムも、beginUpdate時とendUpdate時を比較して、変更、生成、削除、再生成、されたものが格納されます。
typeで配列指定したプロパティのObservableArray変更時のイベント発生順序
DataItemに属するObserevableArrayの中身が変更されると、
- ObservableArrayのchangeイベント
- DataItemのchangeイベント
- DataModelのitemsChangeイベント
- DataModelManagerのitemsChangeイベント
の順にイベントが発火します。
var oAry = item.get('ary');
var order = [];
// oAryのchangeイベントにイベントリスナを登録
oAry.addEventListener('change', function(){
order.push('ObservableArray');
});
// itemのchangeイベントにイベントリスナを登録
item.addEventListener('change', function(){
order.push('Item');
});
// modelのitemsChangeイベントにイベントリスナを登録
model.addEventListener('itemsChange', function(){
order.push('Model');
});
// managerのitemsChangeイベントにイベントリスナを登録
manager.addEventListener('itemsChange', function(){
order.push('Manager');
});
// oAryの中身を変更
oAry.push('a');
order // ['ObservableArray', 'Item', 'Model', 'Manager']
typeで配列指定したプロパティへの値代入時のイベント発生条件
ObservableArrayのchangeイベントは、中身が変更される可能性があるメソッドが実行されると常に発生します。
一方、DataItemのchangeイベントは、メソッド操作によって実際に配列の中身に変更があった場合にのみ発生します。
「実際に配列の中身に変更があった」かどうかは、ObservableArrayのequals()メソッドで操作の変更前後の配列を比較することで判定されます。
item.set('ary', [1, 2, 3]); // 通常、値がセットされるとデータアイテムからchangeイベントが発生する
var oAry = item.get('ary'); //oAryの中身は[1,2,3]
oAry.copyFrom([1, 2, 3]); // [1,2,3] -> [1,2,3] となるのでchangeイベントは発生しない
oAry.slice(0); // slice()では元の配列は変更されないのでイベントは発生しない
oAry.splice(1, 1, 2); // 結果が[1,2,3]となるのでイベントは発生しない
// 以下のいずれも、中身が変更されるためDataItemのchangeイベントが発生する
oAry.copyFrom([1, 2]);
oAry.splice(1, 1, 1);
oAry.push(4);
oAry.reverse();