本記事はWindows 8 Store apps Advent Calendarの13日目の記事です。
3日目の分割アプリケーションとグリッドアプリケーションも書きましたので2巡目ですね。
今回は現在学習中のJavaScript+HTMLプロジェクトでデータバインディングを行う方法を中心にJavaScript+HTMLプロジェクト全般の話をしようと思います。
JavaScriptを触ってみるきっかけは8nights OOSAKAのセッションがすべてJSでの開発事例だったからです(8nightsイベントのレポートは「8 nights OOSAKAに参加して来ました」参照)。
開発中のアプリでもHTMLでデザイン部分、C#でロジックというスタイルを試す機会があったのでちょうど良いタイミングでした。
.NET開発者は勝手知ったるですが、JS+HTMLで開発するような方は案外知らないんじゃないかなと思うんですがどうでしょう?
データバインディングを用いるとロジック(JavaScript)側のコードのプロパティを変更すると連動して表示を変えることができます。
その際に素晴らしいのはJS側の値を適用する表示側のコントロールおよびそのプロパティを知る必要が無いということです。
例えば一般的な例としてJSでHTMLの値を変えるコードは以下です。
// ID=hogeのテキストを変更する hoge.textContent = "変更する値";
この場合HTML側にhogeというIDを振られたコントロールがあること、textContentというプロパティを持つことをロジック側(JS)が知らないとダメということになる。
私の知っているデータバインディングはこの辺の依存を解消してくれる(はず)。
もう一つはJSのプロパティの変更に合わせて見た目を変更する際にデータバインディングを用いないと以下のように合わせて処理を記述する必要がある。
// JSの値を変更 name = "hogeo"; // 同時にHTML側も変更 nameControll.textContent = "hogeo";
これはミスの元だ。
こういう手間もデータバインディングは解消してくれる。
というのがC#の経験からデータバインディングだがJS版はどうだろうか?
データバインディングがどんなものか(うっすら)わかった!!
ではJavaScript+HTMLでこれをやるとどうなるかというと以下のようなコードになる。
<div id="bindArea"> <div id="name" data-win-bind="innerText:nameProp;" ></div> <div id="age" data-win-bind="innerText:ageProp;" ></div> </div>
HTML側は以下のようにあID:bindAreaにnameとageという名前を持った2つのdivタグがありdata-win-bindというプロパティもあります。
data-win-bindの値は”innerText:nameProp;”なんとなくinnerTextの値を書き換えそうな予感がします。
JS側は以下、
var Binding = WinJS.Binding; var person = { nameProp: "Mac", ageProp: 36 }; var personBindSrc; app.onactivated = function (args) { if (args.detail.kind === activation.ActivationKind.launch) { if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) { // TODO: このアプリケーションは新しく起動しました。ここでアプリケーションを // 初期化します。 } else { // TODO: このアプリケーションは中断状態から再度アクティブ化されました。 // ここでアプリケーションの状態を復元します。 } args.setPromise(WinJS.UI.processAll()); Binding.processAll(document.getElementById("bindArea"), person); personBindSrc = Binding.as(person); // データバィンディングの設定 personBindSrc.bind("nameProp", function (newValue) { document.getElementById("name").textContent = newValue; }); // データバィンディングの設定 personBindSrc.bind("ageProp", function (newValue) { document.getElementById("age").textContent = newValue; }); document.getElementById("bindArea").onclick = function () { personBindSrc.nameProp = "hogeMac"; personBindSrc.ageProp = 20; } } };
person変数に格納するオブジェクトがバインド対象のプロパティになるんですが、そのままではだめで
personBindSrc = Binding.as(person);
こんな感じでバインド可能になるように加工してあげます。
バインド可能になったら以下ののようにバインドの設定。
// データバィンディングの設定 personBindSrc.bind("nameProp", function (newValue) { document.getElementById("name").textContent = newValue; }); // データバィンディングの設定 personBindSrc.bind("ageProp", function (newValue) { document.getElementById("age").textContent = newValue; });
すると、bindAreaをクリックすることでnamePropとagePropを書き換えます。
これに連動してHTML側の値も変わります。
JS側の値を変えると自動でHTMLが変わるというのは先にデータバインディングの説明で書いた動きですね。
これで値は変えたけどHTML側を変更するコードを書き忘れたという事態が回避できます。
続いて、バインドする際にロジック(JS)側がHTMLのプロパティを知らないでもいいかというと・・・
// データバィンディングの設定 personBindSrc.bind("nameProp", function (newValue) { document.getElementById("name").textContent = newValue; }); // データバィンディングの設定 personBindSrc.bind("ageProp", function (newValue) { document.getElementById("age").textContent = newValue; });
残念ながらtextContentというプロパティ指定がはっきりと書かれています。
この辺のメリットは享受できない模様、残念。
という感じでC#版よりちょっと見劣りする挙動なJavaScriptのデータバインディング。
単に私がJSでのコーディングに明るくないせいで、本当はもっとデータバインディングするメリットがあるかもしれません。
という感じで多少宿題を残した感じでデータバインディングの説明でした。
ここからは追記、表示側はHTMLで作成してロジックはC#で書こうと思いました。
しかし、C#のobjectをBinding.asメソッドに渡しても拡張不能な変数としてエラー。
C#で拡張可能といえば、DynamicObjectだろうと思ったらWindowsランタイムコンポーネントではDynamicObjectが使えない模様。くそっ、いろいろできないぜWindowsランタイムコンポーネント!!
というわけで、winmetadataの資料をあさっているんですが、確たる情報が得られない・・・・。
この辺は引き続き研究ということで・・・。
Please give us your valuable comment