JavaScriptフレームワークでデータバインディングを試してみる(Ractive.js編)
突然ですが、データバインディングってとても便利ですよね。 仕事ではC#とWPFやActionScriptとFlex(少しだけ)等でデータバインディングを使ったりしています。
C#の場合は、XAML(ザメル、ザムル)というXMLっぽいマークアップ言語で画面(View)を作成し、 各項目(テキストボックス、コンボボックス、グリッド等)の値を独自で作成したModelやDataTable等のオブジェクトのプロパティとバインドします。 バインドすることでView(XAML)とModel(C#のクラス等)の値が連携され、とっても実装が楽になりますしコードがスッキリとします。 そんな便利なデータバインディングですが、最初はこの仕組みがスッと入ってこなかったのを覚えています。(今でも微妙ですけど)
で、C#の話からは離れてJavaScriptの話になるのですが、 Webアプリでもこのデータバインディングを簡単に実現できるJavaScriptのフレームワークがいくつかあるようです。 特に仕事で使う予定もないのですが、4種類(Vue.js, Angular.js, Knockout.js, Ractive.js)のJavaScriptフレームワークを使ってデータバインディングを試してみました。
今回試した上で実装した主な機能は以下です。
- テキストボックスに文字を入力しボタンを押すと入力した内容が一覧に表示される
- テキストボックスに文字を入力すると入力した文字の内容で一覧がフィルタリングされ表示される
実装結果の全体的な動きは以下でご確認ください。
試したフレームワークは4つあるので記事を2つぐらいに分けて書こうと思ったのですが、ちょっと長くなりそうだった(時間もなかった)のでまずは1つ。 今回は「Ractive.js」を。
余談ですが先週、JavaScriptでのデータバインディング関連の以下の記事を書きましたので、宜しければそちらも参照ください。
Vue.jsでチェックされたら or 入力されたら送信可能にするボタンを実装する方法
Ractive.jsとは
Ractive.js - next-generation DOM manipulation
上記が公式サイトですが、「Next-generation DOM manipulation」と大きく書かれています。 日本語にすると「次世代DOM操作」です。かっこいい。 ほんの少ししか触っていないし今まで世代のこともあんまり詳しくないので、 どういう部分が次世代かは分かりませんが、慣れてくるとスゲー便利そうな気はします。
ViewとModelの簡単な説明
View(HTML)
ModelとバインドするViewは
<script type="text/ractive"></script>
で囲んで書きます。 Modelの部分でも書きますが、このタグの内容がテンプレート的な扱いになります。
Model(JavaScript)
上記がRactive.jsのModelの記述です。
「template」にView(HTML)のid(ここでは'#tweetTemplate')を記述し、 そのtemplateを挿入するタグのid(ここでは'#tweet')を「el」に記述しています。
「data」にViewとバインドするModelのプロパティを記述します。 具体的に言うと、HTMLの「value="{{post}}"」は、このModelの「post」プロパティとバインドされ、双方向で値が連携されます。 (ちなみにWPFだとText={Binding PropName}ですね)
Model(JS)側の値を変えるとView(HTML)に反映(表示)され、View(HTML)の値を変えるとModel(JS)の値も変わります。それも即時反映されます。
「テキストボックスに文字を入力しボタンを押すと入力した内容が一覧に表示される」機能の実装
JavaScript側で、Ractiveのonメソッドで「tweets」に入力値を追加するメソッド「addTweet」を登録し、 View(HTML)のボタンに「on-click="addTweet"」を記述することによってクリック時に「addTweet」メソッドが呼ばれるようにしています。
そのメソッド内で、「tweets」というModelのプロパティ(オブジェクト)に入力内容(post)と追加した日時をpushしています。 これでModelの「tweets」に入力内容が追加されます。
この値をViewに一覧表示する箇所がHTMLの以下の部分です。 pushされるとこの部分に表示されます。(すぐにね)
{{#filterTweets():i}} <li> {{post}}({{postedTime}}) <a href="#" on-click="deleteTweet:{{i}}">Delete</a> </li> {{/filterTweets()}}
後述しますが、2のフィルタリング機能を実現するために、dataのfilterTweetメソッド内でfilterWordの値でtweetsをfilterした結果を繰返して表示しています。
「テキストボックスに文字を入力すると入力した文字の内容で一覧がフィルタリングされ表示される」機能の実装
まず、FilterのテキストボックスとModelをバインドします。
<input value="{{filterWord}}">
HTMLの上記の部分です。 これで、テキストボックスの値がModelのfilterWordとバインドされました。
で、ここに何か入力するとその値で一覧をフィルタリングをする実装をしたいわけです。(今回は部分一致です)
それを実現するために、data内にfilterTweetsメソッドを定義しています。 上にも書きましたが、このメソッドがFilterのテキストボックスに入力された値によってtweetsをフィルタリングした結果を返却しており、その返却値(リスト)が一覧に表示されるという具合です。 filterWordもfilterTweetsメソッドもそれぞれViewとバインドされていますので、変更内容はViewに即時反映されます。
まとめ
はじめにも書きましたが、僕個人的には最初はデータバインディング自体がスッと理解できませんでした。 ただやっぱり慣れるもので、慣れてしまえばバインド最高!ってなると思います。 それぐらい便利だと感じています。
てことで、とりあえず今日はRactive.jsでデータバインディングしてみました。 次回はまた別のフレームワークを紹介できればと思っています。