0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FusetoolsAdvent Calendar 2016

Day 22

【Fuse】Observableを極める

Posted at

前のチュートリアルにも出てきたObservable。Fuseをうまく使う上で、重要な概念ですので、より理解を深めるためにリファレンスを読んでみました。

###Observableとは?
まだ知らない方のために一応書いておきます。UXマークアップ側で、UIの値にObservableインスタンスを指定しておくと、指定したObservableの値に変更があったときに、自動でUIのほうにも更新を反映してくれる優れものです。昨日sirizさんが書いてくれた【Fuse】UXマークアップをより強力に!UX Reactive Expressionsにも少し似ていますが、データバインディングなアプリケーションを手軽に実装することができます。

###Sample

簡単なサンプルを作りました。

sample.ux
<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>

loop.gif

Observableを更新すると、購読している全ての要素に伝えられます。

JS経由でスクリーンの幅を取得したかったのですが、フォーラムによると、JSで取得する方法は今のところないようです。requestAnimationFrameもないです。JavaScriptならなんでもありというわけではないみたいですね。

Observableは単一の値だけでなく、リストとして値を保持することもできます。

ObservableList.js
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)で確認できます。

チュートリアルでも使用しましたが、mapwhereのような、reactive operatorsと呼ばれるメソッドとの相性がとてもよいです。一例を示します。

sample.js
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メソッドを使います。先ほどのサンプルに追加すれば、直後でも値が取れるようになります。これのメソッドを使うことにより、変更があった際に何かしらの処理を加えることが可能になります。

sample.js
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が用意されています。次の機会にご紹介します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?