@minop1205前置きKnockout.jsとは?そもそもMVVMパターンとは?Knockout.jsを使うとどのようにコードが変わるか?メリット、デメリットサポートブラウザ使いどころ私の中のJavaScriptの歴史で、Knockout.js(のっくあうと)との出会いはjQueryを知った時以来の衝撃でした。ページの再読み込みではなくJavaScriptによるDOMのリフローを頻繁に行うようなWEBアプリケーションを作成する場合、アプリケーションの規模が大きくなるにつれHTMLマークアップとJavaScriptコードが随所で絡み合ってしまい、次第にコードのメンテナンスや機能拡張が困難になっていきます。そんな経験をしたことのある人は結構多いのではないでしょうか。ここで紹介する「Knockout.js」はそんな問題を劇的に改善してくれるJavaScriptフレームワークです。本来このブログではJavaScriptそのものについての理解を深めるというテーマのもと、この言語が持つ特徴やコーディングパターンなどをメインにエントリを書いてきました。JavaScriptライブラリ/フレームワークやjQueryブラグイン等の使い方については触れない予定でしたが、最近私が実務で使い出したJavaScriptフレームワーク「knockout.js」が本当に便利で、もっと使いこなしたいと思うようになってきたので、自身の勉強も兼ねてしばらくはknockout.jsについてのエントリを書いていこうと思います。Knockout.jsとは?Knockout.jsを一言でいうと、「MVVM(Model-View-ViewModel)パターンをサポートするためのJavaScriptフレームワーク」です。それ自身が純粋なJavaScriptで作成されているため、Webサイト・Webアプリケーションに簡単に導入することができます。MVVMパターンをサポートするJavaScriptフレームワークはKnockout.js以外にもいくつかあるようですが、当ブログではKnockout.jsに焦点を絞ってエントリを書いていきます。その他のフレームワークの概要やそれぞれの長所、短所等が知りたければ以下のサイトが参考になると思います。[キータ]Knockout.jsを「JavaScriptライブラリ」と紹介している記事をたまに見かけますが、その性質上ライブラリというよりは「JavaScriptフレームワーク」の方が意味合いとしては正しいと思うので、本エントリではフレームワークとして紹介します。Knockout.jsはフレームワークなので、jQueryのようなJavaScriptライブラリとは基本的に別物です。jQueryを置き換えるようなものではありませんし、もちろん共存させることも可能です。これまでDOM操作の大部分をjQueryベースで実現していたようなケースでは、そのほぼ全てをKnockout.jsに置き換えることができます。jQueryを使った場合よりも、HTML、JavaScriptの両者のコードを分離しやすくなるはずです。そもそもMVVMパターンとは?MVVMパターンについては既にたくさんの有益な情報がネット上にありますので、私がここで下手な解説をするよりはググってもらった方がよっぽど正しく理解できると思います。プレゼンテーション(Presentation)とドメイン(Domain)の分割を目的としたMVC系のパターンの1つで、アプリケーションのコードをModel、View、ViewModelという3つの責務に分割して記述します。ここでのプレゼンテーションとはユーザインタフェース(UI)を実装するプラットフォームに依存した部分、ドメインはプラットフォームに依存しない部分を指しています。Webアプリで言えば、プレゼンテーションはHTMLの都合が関係ある部分、ドメインはHTMLの都合が関係ない部分になります。引用元:[Knockout]MVVMパターンでアプリケーションを構築する・・・が、一応私なりの理解の仕方で「WEBアプリケーションの場合のMVVMパターン」について整理してみました。所々間違っているかもしれませんので、あくまでも参考程度でお願いします。システム全体をクライアントサイドとサーバサイドに分ける。MVVMはクライアントサイドのコードに適用されるパターンなのでサーバサイドについては関知しない。クライアントサイドとサーバサイドの連携には通常、AJAX(SOAP、RESTなど)が使われる。クライアントサイドのコードを、HTMLの都合が関係ある部分=プレゼンテーション(Presentation)とHTMLの都合が関係ない部分=ドメイン(Domain)とに分けるプレゼンテーションを、UIのテンプレートを定義するHTML/CSS=ビュー(View)と、UIの状態の保持、およびUIから呼び出されるメソッドを定義したJavaScript=ビューモデル(ViewModel)とに分けるこのことを、MVVM(Model-View-ViewModel)の各セクションに当てはめて整理すると、以下の様になります。M(Model)クライアントサイドのコードの内、HTMLの都合が関係ない部分(ドメイン)のロジックを実装するJavaScriptコード。Webサービスの呼び出しや、共通して使われる汎用的なコード(ライブラリ)など。V(View)クライアントサイドのコードの内、UIのテンプレートを定義するHTML/CSS。VM(ViewModel)クライアントサイドのコードの内、UIの状態保持、および、UIから呼び出されるメソッドを定義したJavaScriptコードさて、ここでポイントとなるのは、ViewとViewModel間との連携です。ViewModelは「UIの状態の保持」と書きましたが、このViewModelの中のUIの状態は、例えば「状態保持オブジェクト」のようなものを作成し、そこにUIの状態を書き込んでいくことになると思います。すると、このUIの状態(=状態保持オブジェクトのプロパティの値)をどのようにしてViewに反映させるのでしょうか?実は、MVVMパターンではViewとViewModel間との連携は「データバインド」と呼ばれる仕組みを通じて行うことが前提になっています。データバインドは通常、Knockout.js等のフレームワーク側が行うものなので、サイト制作者がこの仕組みを構築する必要はありません。フレームワーク側はViewModelが持っているUIの状態(状態保持オブジェクト)の内容を監視し、このオブジェクトの内容をView側(つまりHTML)に反映させたり、逆にView側の変化をオブジェクトに反映させたりすることができます。データバインドはViewの内容とViewModelの「状態保持オブジェクト」の紐づけをしてくれるのです。一度紐づけが行われたら、以降はView/ViewModelのどちらか一方の状態が変化した場合も、リアルタイムでもう一方の状態も更新されるようになります。このことは次の様なメリットをもたらします。DOM操作のためのJavaScriptコードがほとんど不要になるUIへの入出力のためにHTML要素へのid設定が不要になるDOM構造を意識せずにModelを作成できるMVVMパターンを導入することによって、UIデザイナ/マークアップエンジニアとJavaScriptプログラマとの分業がしやすくなるというわけです。Knockout.jsを使うとどのようにコードが変わるか?例えばユーザのアクションに応じてUIを変化させる必要があるような場合、どのような方法で実現しますか?jQueryのようなライブラリを使って、イベントハンドラ(関数)を作成し、ハンドラの中にDOMを操作するためのコードをゴリゴリと書いていく、そんなやり方がスタンダードだったのではないでしょうか。)以下は、ボタンをクリックするとリスト(<ul>要素)の中身が増えていくというシンプルな機能をKnockout.jsを使わずにjQueryで書いた例です。$ul.append($li);});上記と同じ機能をjQueryを使わずに、今度はKnockout.jsを使って書いた例が下記になります。};//状態保持オブジェクトとHTMLテンプレートを紐づけするko.applyBindings(viewModel);Knockout.jsの良さをまるで伝えられていないサンプルコード(しかも、この程度の機能の場合Knockout.jsの方がコード量が多くなってしまっているような気がします。)ですが、ここで注目してもらいたいのは、Knockoutを使ったコードの方では、JavaScriptコード側で一切のDOMの操作をしていないということです。Knockout.jsではHTML側で「テンプレート」を定義し、「テンプレートの状態」はJavaScript側に持たせます。テンプレートとテンプレートの状態は、先ほどのデータバインドの仕組みによりお互いが紐づけられます。DOMを変更する場合は、JavaScript側でDOMを直接操作するのではなく、テンプレートの状態(サンプルコードのitemsの値)を更新することにより自動的にHTML側のレンプレートに反映されます。上記のKnockout.jsサンプルの方では、HTMLコードとJavaScriptコードの両者に見慣れない記述がありますが、これはKnockout.js固有のコードです。本エントリではまずはKnockout.jsの概要に絞って解説していますので、これらの意味については別エントリで紹介します。いえ既にKnockout.jsについてはドキュメントも公開されていますので、興味があれば下記サイトをチェックしてみて下さい。▼Knockout(本家サイト)http://knockoutjs.com/▼ドキュメントKnockout.js(非公式翻訳ドキュメント)http://kojs.sukobuto.com/メリット・デメリットメリット1:マークアップの変更に強い上のサンプルコードで、例えば追加するli要素にclass属性等の何らかの属性を付けたい場合、前者(jQuery版)の場合だとJavaScriptコードを修正しなければなりません。これに対し、後者(Knockout.js版)の方では、マークアップの変更はHTMLテンプレート側で行えば良いだけですので、JavaScriptの修正は必要ありません。HTML側からすればJavaScriptのコードの内容は関係ありません。HTML側とJavaScript側の唯一の接点であるViewModelの構造さえ共有できていれば、両者は互いに自由に修正を行うことが可能になるのです。デザイナーがHTML/CSSのマークアップを行い、JavaScriptコーディングをプログラマが行うといケースはわりとよくあるのではないかと思います。前者(jQuery版)の方では、デザイナーはUIの見た目を修正するために一部のマークアップを変更したいだけなのに、対象のHTMLマークアップがJavaScript側にあるため、その都度プログラマに修正依頼をしなければなりません。これに対し、Knockout.jsを使用しているケースでは、あくまでもHTML側のみでテンプレートが定義されているので、デザイナーは自由にマークアップを変更することが可能になります。メリット2:冗長なid、class設定が不要になるjQueryを使ってDOMの操作を行う場合、操作対象のHTML要素を特定する必要があります。したがって、操作対象のHTML要素にJavaScriptからアクセスするためのidやclass属性を付加する必要があります(必ずしも付加する必要はありませんが、jQueryで要素を特定する際のセレクタが冗長になります)。Knockout.jsではJavaScript側でDOMの操作を行いません。したがってHTML要素にidやclass属性を付加する必要がありません。メリット3:HTMLとJavaScriptの分離Knockout.jsではHTML側のコードにJavaScriptコードは入りません。Knockout.jsを使うためのバインディングと呼ばれる記述は必要ですが、data-bind属性を使ったHTMLレベルでの記述です。JavaScript側のコードにはDOM操作のためのコードは入りません。役割分担の明確化メンテナンス性の向上といったメリットをもたらします。このようにKnockout.jsを使うとさまざまなメリットを享受することができますが、唯一のデメリット(というべきかどうかは分かりませんが)は、HTMLマークアップ内にKnockout.js固有の「バインディング」を記述する必要があるということです。時には複雑なバインディングを記述する必要があるかもしれません。これはMVVMパターンを使う場合の前提であり当たり前のことなのですが、せっかくHTMLとJavaScriptを分離できたとしても、HTML側に複雑なバインディングを書かなくてはならないようなケースではそのメリットも半減してしまうかもしれません。(多くの場合は設計を見直すことで、よりシンプルなバインディングに書き換えられるとは思いますが。)ただ、バインディング自体はそこまで難しいものではないと思いますし、暗記する必要も無いでしょう。(私自身バインディングはほとんど暗記していません)必要に応じて上で紹介しているようなサイトを見ながらコーディングしていけるはずです。supportに書かれています。英文ですので一応日本語に訳してまとめておいたのですが、英語力がゼロに等しい私としては是非原文を参考にしていただきたいと思います。browser対応(バージョン記載なし)使いどころKnockout.jsは「MVVM(Model-View-ViewModel)パターンをサポートするためのJavaScriptフレームワーク」ですので、MVVMパターンを適用できるようなWEBアプリケーションを構築する際に利用すべきでしょう。サーバサイドでDOMの構築を完了させ、ユーザーアクションの都度ページの再読み込みを行うような通常のWEBサイトを構築するのであれば、Knockout.jsの必要性はほとんどないと思います。クライアント側でDOMの振る舞いをちょこっと変える程度であれば、jQueryだけで十分です。これに対し、AJAX通信で取得したJSONデータの内容に応じて頻繁にDOMの書き換えをおこなうようなリッチWEBアプリケーション(このようなWEBアプリケーションのことを「シングルページアプリケーション(SPA)」と言ったりします)を構築する場合にKnockout.jsは絶大な力を発揮します。GmailのようなWEBメールクライアントだったり、Twitterクライアントツールの様な物でしょうか。(実際にこれらのツールがKnockout.jsの様なフレームワークを使用しているかどうかは分かりませんが)企業サイトやブランドサイトの様なものよりは、どちらかというとユーザーがツールとして使えるようなWEBアプリ向けのフレームワークだと思います。個人的には、このようなWEBアプリケーションはサービスの提供手段としては、今後より一般的になって来るのではないかと思います。ゆえに、Knockout.jsの様なJavaScriptフレームワークは今後ますます注目されるのではないかと感じています。今回はKnockout.jsの概要についてまとめましたが、次回以降はもう少し掘り下げた内容を書いていきます。皆さんも機会があれば是非挑戦してみてくださいね。2016年9月30日サイトマップ。