前のチュートリアルにも出てきたObservable
。Fuseをうまく使う上で、重要な概念ですので、より理解を深めるためにリファレンスを読んでみました。
###Observableとは?
まだ知らない方のために一応書いておきます。UXマークアップ側で、UIの値にObservable
インスタンスを指定しておくと、指定したObservable
の値に変更があったときに、自動でUIのほうにも更新を反映してくれる優れものです。昨日sirizさんが書いてくれた【Fuse】UXマークアップをより強力に!UX Reactive Expressionsにも少し似ていますが、データバインディングなアプリケーションを手軽に実装することができます。
###Sample
簡単なサンプルを作りました。
<App>
<JavaScript>
//Observableパッケージをインポート
var Observable = require('FuseJS/Observable');
//Observableインスタンスを生成
var pos = new Observable(0);
//Observableの値を更新する
function move() {
if(pos.value > 375) {
pos.value = -50;
}
pos.value += 1;
}
function loop() {
move();
setTimeout(loop, 10);
}
loop();
// ObservableインスタンスをUXマークアップ側に公開する
module.exports = {
posX : pos
}
</JavaScript>
<ClientPanel>
<StackPanel Alignment="Top">
<Rectangle Alignment="Left" Width="50" Height="50" Color="Red" Margin="0,10,0,0">
<!-- JSから公開されたposXを値として設定する。 -->
<Transltion X="{posX}" />
</Rectangle>
<Rectangle Alignment="Right" Width="50" Height="50" Color="Blue" Margin="0,10,0,0">
<!-- JSから公開されたposXを受け取って-1をかけて設定する。 -->
<Translation X="{posX} * -1" />
</Rectangle>
</StackPanel>
</ClientPanel>
</App>
Observable
を更新すると、購読している全ての要素に伝えられます。
JS経由でスクリーンの幅を取得したかったのですが、フォーラムによると、JSで取得する方法は今のところないようです。requestAnimationFrameもないです。JavaScriptならなんでもありというわけではないみたいですね。
Observable
は単一の値だけでなく、リストとして値を保持することもできます。
var PPAP = Observable("P", "P", "A");
console.log(PPAP.length); // 3
PPAP.add("P"); // リストの最後に値を追加する
console.log(PPAP.length); // 4
console.log(PPAP.getAt(2)); // "A"
※console.logの値はFuse Monitor([Cmd or Ctrl] + M)で確認できます。
チュートリアルでも使用しましたが、map
やwhere
のような、reactive operators
と呼ばれるメソッドとの相性がとてもよいです。一例を示します。
var someNumbers = Observable(1,2,3,4);
//リストの各項目を2乗したリストを持つ新しい`Observable`インスタンスを生成します。
var someNumbersSquared = someNumbers.map(function(x){ return x * x; });
console.log(someNumbersSquared.getAt(3)) // null!!!
ただし、reactive operator
の直後は値を取れないことに注意してください。リスナーが登録されていないと、変更が伝播されないためです。
リスナーを追加するには、先のサンプルで示したように、UXマークアップ側で{hoge}
というように指定するやりかたが一般的です。しかしJS側でリスナーを登録することもできます。
###JSの中でObservable
の変更を受け取る
JSでObservable
の変更を受け取るには、onValueChanged
メソッドを使います。先ほどのサンプルに追加すれば、直後でも値が取れるようになります。これのメソッドを使うことにより、変更があった際に何かしらの処理を加えることが可能になります。
var someNumbers = Observable(1,2,3,4);
//リストの各項目を2乗したリストを持つ新しい`Observable`インスタンスを生成します。
var someNumbersSquared = someNumbers.map(function(x){ return x * x; });
someNumbersSquared.onValueChanged(module, function(item){
//なにかしらの処理
});
console.log(someNumbersSquared.getAt(3)); //16
単にリスナーを追加する、addSubscriber(function(){ })
もあるのですが、これはリスナーを削除するときに、removeSubscriber
を明示的に実行する必要があるので、.onValueChanged
を推奨しています。
その他にも、Observable
には、いろんなAPIが用意されています。次の機会にご紹介します。