ObservableArray
概要
ObservableArray(オブザーバブルアレイ)は、配列への操作を検出しイベントを送出する配列(※)です。
通常の配列と同じように使うことができ、その際の関数呼び出しを検出して要素の追加、削除、変更等を監視することができます。
(※厳密には、配列と同等の関数を持つオブジェクトです。)
ObservableArrayのAPIドキュメントは、
をご覧ください。インスタンスの生成・使い方
ObservableArrayは、h5.core.data.createObservableArray()メソッドを使って作成します。
var obsAry = h5.core.data.createObservableArray();
// Arrayが持つメソッドを使うことができる
obsAry.push('A'); // ['A']
obsAry.unshift('B'); // ['B', 'A']
// ObservableArrayが独自に持つメソッド
obsArray.copyFrom(['A', 'B', 'C']);
//obsArrayの中身は['A', 'B', 'C']になる(既に要素が入っていた場合は全て取り除かれる)
//要素はシャローコピーされる
obsArray.equals(['A', 'B', 'C']);
使用上の注意
配列の要素(値)を取得するときは必ずget()メソッドを使用する
以下のようなコードでは、値を取得できません。
var val = sampleObsArray[2];
以下のようにget()メソッドを使用して下さい。
配列に要素をセットするときは必ずメソッドを使用する
以下のようなコードでは、変更を検出できません(配列に正しく値がセットされません)。
sampleObsArray[2] = 'newValue';
配列中の特定のインデックスの値を変えたい場合は、set()メソッドを使用してください(ver.1.1.3以降)。
obsArray.push('A', 'B', 'C');
obsArray.set(1, 'newValue'); // ['A', 'newValue', 'C'] になる
配列を要求する関数にインスタンスを渡す際は、必要に応じてtoArray()を呼んで通常の配列にする
たとえばネイティブの配列はconcat()メソッドを持ち、引数に連結する配列をとります。
このとき、以下のようにすると、newArrayは意図した(連結された)配列になりません。
これは、ObservableArrayが実際には(配列ではなく)オブジェクトとして認識されるためです。
意図した通りに動作させるためには、obsArray.slice(0) または obsArray.toArray() を呼んで、通常の配列にしてください。
(※toArray()は、ver.1.1.2で追加されました。)
//newArrayはネイティブの配列インスタンス
イベントリスナの登録
ObservableArrayにイベントリスナを登録することで、メソッドによる操作を監視することができます。
addEventListener()メソッドを使い、changeBefore、changeイベントに、それぞれ処理実行前、処理実行後のイベントリスナを登録します。
function beforeListener(ev){
// ここに配列操作前に行いたい処理を記述
alert('メソッド"' + ev.method + '"が呼ばれました');
}
function changeListener(ev){
// ここに配列操作後に行いたい処理を記述
alert('メソッド"' + ev.method + '"の処理を実行しました');
}
var obsAry = h5.core.data.createObservableArray();
obsAry.addEventListener('changeBefore', beforeListener);
obsAry.addEventListener('change', changeListener);
// メソッド呼び出すと、beforeListener→メソッドの実行→changeListenerの順で実行される
obsArray.copyFrom([1, 2, 3]);
イベントリスナに渡されるイベントオブジェクトは以下のような構造です。
type: /* "changeBefore" または "change" */,
method: /* メソッド名 */,
args: /* メソッド呼び出し時に渡された引数 */,
returnValue: /* changeイベントの場合のみ。メソッドが返す値 */,
target: /* ObservableArrayインスタンス */,
preventDefault: /* changeBeforeイベントの時に実行すると配列操作をキャンセルする関数 */,
stopImmediatePropagation: /* 以降のハンドラを、全て実行しないようにする関数 */
}
ただし、データアイテムが持つObservableArrayで、データアイテムが属しているデータモデルマネージャのbeginUpdate()/endUpdate()によってアップデートセッションが管理されている場合、changeイベントはendUpdate()のタイミングで発生し、イベントオブジェクトのmethod、args、returnValueはnullになります。
例
以下のコードでは、配列へのnull、undefinedが代入されたら警告を出します。
function beforeListener(ev){
// 配列に要素が追加される可能性のあるメソッドなら、その引数をチェックする
if ($.inArray(ev.method, ['unshift', 'push', 'splice', 'copyFrom'])) {
// argumentsオブジェクトを配列に変換
var args = h5.u.obj.argsToArray(ev.args);
if (ev.method === 'splice') {
if (args.length <= 2) {
// spliceに引数が2つ以下なら要素追加はないので、チェックしない
return true;
}
// spliceの場合、第3引数以降をチェック対象にする
args.shift();
args.shift();
}
// nullまたはundefinedが含まれているかどうかチェックする
for (var i = 0, l = args.length; i < l; i++){
if (args[i] == null){
// null,undefinedが含まれていたら、警告を出す
alert('nullまたはundefinedが入れられました');
}
}
}
}
function changeListener(ev){
// ここに配列操作後に行いたい処理を記述
alert('メソッド"' + ev.method + '"の処理を実行しました');
}
var notNullArray = h5.core.data.createObservableArray();
notNullArray.addEventListener('changeBefore', beforeListener);
notNullArray.addEventListener('change', changeListener);
notNullArray.copyFrom([1, 2, 3]); // 'メソッド"copyFrom"の処理を実行しました'
notNullArray.copyFrom([1, 2, null]); // 'nullまたはundefinedは入れられました' 'メソッド"copyFrom"の処理を実行しました'