開発者ブログ
リファレンス(仕様詳細) » データモデル機構のイベント詳細

データモデル機構のイベント詳細

Last modified by fukudayasuo on 2014/01/20, 17:39

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されたインスタンスが入ります。

コード例:

// データアイテムを4つ生成
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イベントにマージされます。

// データアイテムを4つ生成
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!」の順にアラートが表示される
各データアイテムのプロパティが「変更された」とみなすかどうかは、beginUpdate()時とendUpdate()時の状態から決定されます。
上記の例では、item1の値はbeginUpdate()時に「1」、endUpdate()時に「1」なので、「値は変更されなかった」とみなされます。したがって、item1のイベントリスナー(listener1)は実行されません。

上記の例での、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の中身が変更されると、

  1. ObservableArrayのchangeイベント
  2. DataItemのchangeイベント
  3. DataModelのitemsChangeイベント
  4. DataModelManagerのitemsChangeイベント

の順にイベントが発火します。

// aryにObservableArrayを持つデータアイテムitem

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()メソッドで操作の変更前後の配列を比較することで判定されます。

var item = model.create();

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

Copyright (C) 2012-2017 NS Solutions Corporation, All Rights Reserved.