宣言的なJSフレームワーク デモ解説(1)
概要
KnockoutにあるchooseTicketの例をdata-x.jsで作るとどうなるかを解説する。
フレームワーク
デモ概要
チケットの種類を選択すると、価格を含むメッセージを表示する。
クリアボタンを押すと、選択しているチケットをクリアする。
ソース解説
index.html
フレームワークの読み込み
mainという名前のブロックをロードする。バインドルールを外部ファイルで持つ。
フレームワークの実行。scriptタグのtype属性にmoduleを指定。
index-spa/css、index-spa/html、index-spa/module
ブロックを入れるフォルダ。ブロックはcss、html、JSモジュールで構成される。ファイル名は、ブロック名+拡張子(.css, .html, js)。
main.html
mainブロックのhtml。
selectタグのname属性の値("ticketId|number-value")は、viewModelのticketIdプロパティとバインドし、number-valueフィルターを適用する。number-valueフィルターは、viewModelのプロパティ値を数値型として扱う。
配列データの繰り返しは、繰り返す要素をtemplateタグで囲む
buttonタグは、暗黙的にviwModelのclickイベントハンドラを実行する。clickイベントハンドラ名は、event+イベント名+buttonのname属性。ここでは、eventClickClearとなる。
main.js
mainブロックのjsモジュール。ViewModelのクラス定義、プロパティ依存関係ルールの定義とそれらのエクスポートを行う。
チケットの配列データ。
ViewModelのクラス定義。AppViewModelという名前でクラスを作成する。
データプロパティは、"@"もしくは"@@"+プロパティ名で定義する。
"@"はリードオンリー、"@@"は書き込み可(双方向バインド)を示す。
プロパティ名のあとに"#"を続けて、get/set/initの関数を定義することができる。
イベントハンドラは、"#"+イベントハンドラ名で定義する。
optionタグとバインドするプロパティ。繰り返す要素は、アスタリスクを含むドット記法で記述する。
selectタグのvalueとバインドするプロパティ。選択したチケットIDを保存する。書き込む必要があるので"@@"とする。バインド時number-valueフィルタを使っているので、ticketIdは数値型として扱われる。
選択したチケットの情報。findで選択したチケットIDに一致するものを探す。ticketIdは数値型なので、===で評価できる。
イベントハンドラ、クリアボタンを押したときの動作。選択したチケットをクリアする。
プロパティ間の依存関係ルール。
[ "ticket", [ "ticketId" ] ],
の意味は、ticketIdプロパティが更新されたら、ticketの値をバインドしているhtml要素の属性へ反映する。
デフォルトエキスポートを行う。
main.bind.css
mainブロックのバインドルール。
CSSと同じような感じで使う。対象のhtml要素をセレクタで指定し、バインドルールを定義していく。
バインドルールは、
--bind-html要素のプロパティ: viewModelのプロパティ
フィルターをつける場合、viewModelプロパティの後に、|でフィルター名を続ける。
html要素のプロパティが、階層を持つ場合、-で区切る
例
--bind-style-display: ticket|style-display;
リストなどのように要素を繰り返す場合、templateに--loop: リストのプロパティを指定する。
繰り返すリストの設定。--loopとし、繰り返すリストのプロパティ名を指定する。ここでは、viewModelのticketsプロパティ。
繰り返す要素の設定。optionのvalue属性とviewModelのプロパティ"tcikets.*.id"、optionのtextContent属性とviewModelのプロパティ"tcikets.*.name"をバインドする。アスタリスクを含むドット記法でそのまま指定する。templateタグをまたいだセレクタは指定できないことに注意する。
クリアボタンのdisabled属性とviewModelのプロパティticketをバインド。falseyフィルターはviewModelの値がfalseyな場合、trueとなる。チケットを選択した場合、クリアボタンが有効となる。
メッセージを表示する領域のstyle.display属性とviewModelのプロパティticketをバインド。style-displayフィルターは、viewModelの値が真の場合""、偽の場合"none"を返す。チケットを選択した場合、メッセージを表示する。
メッセージに表示する名前と価格をそれぞれviewModelのプロパティticket.nameとプロパティticket.priceとバインドする。
感想
knockoutよりも長くなった。
繰り返す部分を変数など使わず*を用いて宣言的に定義できたので満足。
Discussion