Observable Array
もしひとつのオブジェクトの変更を検知し、反応させたいのであれば Observable を使って下さい。
もしコレクション (配列) の変更を検知し、反応させたいのであれば observableArray
を使って下さい。
これは複数の値を表示もしくは編集できるようにする場面や、アイテムの追加・削除により UI の繰り返し部分を出現・消滅させるといった場面で役に立ちます。
例
var myObservableArray = ko.observableArray(); // 最初は空の配列 myObservableArray.push('何らかの値'); // 値を追加し、監視側に通知する
observableArray
を UI にバインドし、ユーザに変更させる方法は
the simple list example をご覧ください。
キーポイント
observableArray が把握するのは“どのオブジェクトが配列に含まれるのか”であり、“それぞれのオブジェクトの状態”ではありません。
単に observableArray
にオブジェクトを追加しただけでは、そのオブジェクトのプロパティは監視されません。
もちろん、望むならばそれらのプロパティを Observable にすることができますが、それは別の課題です。
observableArray
は単純に、どのオブジェクトを保持しているかを把握し、追加・削除された際に監視側に通知します。
observableArray に初期値を設定する
もし空の observableArray ではなく、初期値としてアイテムを設定したいのであれば、 次の例のようにコンストラクタに配列を指定して下さい。
// この Observable Array は最初から3つのオブジェクトを持ちます var anotherObservableArray = ko.observableArray([ { name: "Bungle", type: "Bear" }, { name: "George", type: "Hippo" }, { name: "Zippy", type: "Unknown" } ]);
observableArray から情報を取得する
舞台裏では、observableArray
は実際のところ、値が配列である Observable です。
(加えて、observableArray は後述の特徴を含みます。)
そのためほかの Observable と同様に、observableArray
を引数なしで関数として呼び出すことで、背後にある JavaScript 配列 を取得することができます。
そうしたら次のように、背後の配列から情報を取得できます。
alert('配列の要素数: ' + myObservableArray().length); alert('最初の要素: ' + myObservableArray()[0]);
技術的には、JavaScript 標準の配列の機能は、背後にある配列を操作するために全て使うことができます。 しかし通常は、よりよい選択肢があります。 Knockout の observableArray は同様の機能を持っており、それらは以下の理由からより便利なのです。
- すべての対象ブラウザに対して互換性があります。 (例えば、IE8以前では indexOf 関数が使えませんが、Knockout の indexOf は使えます。)
-
push
やsplice
などの配列の要素を操作する関数において、 Knockout のメソッドは依存トラッキングメカニズムを自動的に引き起こすため、 すべての登録されたリスナに対して変更が通知され、UI が自動更新されます。 -
構文がより便利です。
Knockout の
push
メソッドを呼ぶには、myObservableArray.push(...)
と書けばOKです。myObservableArray().push(...)
と書くよりかは多少よいでしょう。
このページの残りの部分では、observableArray
の配列の情報を読み書きする機能について説明します。
indexOf
indexOf
関数は、配列の中で指定したパラメタに一致する要素が最初に見つかったインデックスを返却します。
例えば、myObservableArray.indexOf('あいう')
とした場合、あいう
に一致する要素があれば
その要素のゼロベース・インデックスを返します。一致する要素がみつからない場合は -1
を返します。
slice
slice
関数は、JavaScript 標準配列の slice
関数と同等です。
(引数に与えられた開始インデックスと終了インデックスをもとに、配列から切り出した要素を返却します。)
myObservableArray.slice(...)
と myObservableArray().slice(...)
の結果は等価です。
observableArray に対する変更
observableArray
は配列の内容を変更し、かつリスナに通知するよく知られた形の関数群を提供しています。
pop, push, shift, unshift, reverse, sort, splice
これらの関数は全て JavaScript 標準配列の関数と同等の動作をし、かつリスナに対して変更を通知します。
myObservableArray.push('新しい値')
配列の末尾に要素を追加します。myObservableArray.pop()
配列から末尾の要素を削除・返却します。myObservableArray.unshift('新しい値')
配列の先頭に要素を挿入します。myObservableArray.shift()
配列から先頭の要素を削除・返却します。myObservableArray.reverse()
配列の要素順を反転します。-
myObservableArray.sort()
配列の要素をソートします。- デフォルトで、アルファベット順もしくは数値順にソートします。
-
オプションとして、ソートのための評価関数を指定できます。
評価関数は配列から2つのオブジェクトを引数として受け取り、
1つめのオブジェクトが小さければ負の数値を、2つめのオブジェクトが小さければ正の数値を、
等価であれば 0 を返却するようにして下さい。
例えば、'person' オブジェクトをラストネームでソートする場合、次のようにします。
myObservableArray.sort(function(left, right) { return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1); });
-
myObservableArray.splice(startIndex, length)
startIndex に位置する要素から length 個分の要素を配列から削除・返却します。 例えば、myObservableArray.splice(1, 3)
とすると インデックス 1 から続く3つの要素 (つまり2, 3, 4 番目の要素) を削除し、配列として返却します。
これらの observableArray
の関数について詳しく知りたい場合は、同等の
JavaScript 標準の配列関数のドキュメントを参照して下さい。
remove と removeAll
observableArray
には JavaScript 標準配列にはないより便利なメソッドがあります。
myObservableArray.remove(someItem)
someItem
に一致する要素を全て削除し、それらを配列として返却します。myObservableArray.remove(function(item) { return item.age < 18 } )
プロパティage
が18 より小さい要素を全て削除し、それらを配列として返却します。myObservableArray.removeAll(['Chad', 132, undefined])
'Chad', 123, undefined
に一致する要素を全て削除し、それらを配列として返却します。myObservableArray.removeAll()
全ての要素を削除し、それらを配列として返却します。
destroy と destroyAll (※通常、Ruby on Rails を使用した開発にのみ関係します)
destroy
関数と destroyAll
関数は主に Ruby on Rails を使用した開発に対する利便性のためにあります。
myObservableArray.destroy(someItem)
someItem
に一致するオブジェクトを全て検索し、それらに_destroy
という特別なプロパティを値true
とともに付与します。myObservableArray.destroy(function(item) { return item.age < 18 } )
プロパティage
が18 より小さいオブジェクトを全て検索し、それらに_destroy
という特別なプロパティを値true
とともに付与します。myObservableArray.destroyAll(['Chad', 132, undefined])
'Chad', 123, undefined
に一致するオブジェクトを全て検索し、それらに_destroy
という特別なプロパティを値true
とともに付与します。myObservableArray.destroyAll()
全てのオブジェクトを検索し、それらに_destroy
という特別なプロパティを値true
とともに付与します。
_destroy
とはなんぞや?という話ですが、 Rails デベロッパーにとってのみ本当におもしろいものです。
Rails の便利なところは、JSON オブジェクトグラフをアクションに渡すと、
フレームワークが自動的に ActiveRecord オブジェクトグラフに変換しデータベースに保存してくれることです。
オブジェクトがデータベースに既に存在するかを把握しており、INSERT文 または UPDATE文を正しく発行してくれます。
フレームワークにレコードの削除を伝えるには、_destroy
を true
にして削除フラグを立てるだけです。
留意点として、Knockout は foreach
バインディングをレンダリングする際、
_destroy
プロパティが true
になっているオブジェクトを自動的に隠します。
したがって、“削除”ボタンの類で destroy(someItem)
を発動させることで、
即座に UI から対象のアイテムを消滅させることができます。
その後、JSON オブジェクトグラフを Rails に送信することで、それらのアイテムは
データベースからも削除されるという算段です。
(配列のその他の要素は、通常通り挿入または更新されます)