#概要
jQueryから抜け出せないレガシーなエンジニアが、knockout.jsの公式サイトのチュートリアルを実践した際の自分用メモ。
(チュートリアルでやったことをあとで俯瞰できるように、自分なりのメモとか翻訳した文章を加筆したものです。)
#MVVM(Model-View-ViewModel)とはなんぞや?
まず、基本の勉強。
MVVMフレームワーク「Knockout.js」が超絶便利!!その概要と使いどころなどについて より
###M(Model)
クライアントサイドのコードの内、HTMLの都合が関係ない部分(ドメイン)のロジックを実装するJavaScriptコード。
Webサービスの呼び出しや、共通して使われる汎用的なコード(ライブラリ)など。
###V(View)
クライアントサイドのコードの内、UIのテンプレートを定義するHTML/CSS。
###VM(ViewModel)
クライアントサイドのコードの内、UIの状態保持、および、UIから呼び出されるメソッドを定義したJavaScriptコード
#公式チュートリアル実践
Tutorial: Introduction
See the Pen KOJS tutorial1 for myself by Yanchi4425 (@yanchi4425) on CodePen.
Tutorial: Working with Lists and Collections
See the Pen KOJS tutorial2 for myself by Yanchi4425 (@yanchi4425) on CodePen.
Tutorial: Single Page Application
このコードを直接貼り付けても"/mail"が無いので動きません。
動かしたい場合は、公式のチュートリアルページで実行する必要があります。
もしくは、以下に本チュートリアルの完成形があります。
http://learn.knockoutjs.com/WebmailExampleStandalone.html
http://learn.knockoutjs.com/mail?folder=inbox
のようにすると一応/mailから返されるデータを見ることができます。
<style>
body {
color: black;
}
.selected {
background-color: #7f7;
}
</style>
<ul class="folders" data-bind="foreach: folders">
<!-- CSSバインディングを使用して、選択したクラスを一致するフォルダに適用したり、
ユーザーがフォルダをクリックするたびにgoToFolderを呼び出すことができます。 -->
<li data-bind="text: $data, css: {selected: $data == $root.chosenFolderId()}, click: $root.goToFolder"></li>
</ul>
<!-- step2 -->
<!-- Mails grid -->
<!-- withバインディングは、その中の要素をバインドするときに使用されるバインディング・コンテキストを作成します。
この例では、<table>内のすべてがselectedFolderDataにバインドされるため、
selectedFolderDataを使用する必要はありません。
メールの前にプレフィックスとして。
-->
<table class="mails" data-bind="with: chosenFolderData">
<thead>
<tr>
<th>From</th>
<th>To</th>
<th>Subject</th>
<th>Date</th>
</tr>
</thead>
<tbody data-bind="foreach: mails">
<!-- step3 -->
<!-- バインドを更新する必要があるため、訪問者がメールグリッドの行をクリックすると、
ビューモデルが対応するメールをロードするようにする。
なんで、<tr>要素のクリックバインドを追加する。 -->
<tr data-bind="click: $root.goToMail">
<td data-bind="text: from"></td>
<td data-bind="text: to"></td>
<td data-bind="text: subject"></td>
<td data-bind="text: date"></td>
</tr>
</tbody>
</table>
<!-- step3 -->
<!-- 選択されたメールの内容を表示する -->
<!-- Chosen mail -->
<div class="viewMail" data-bind="with: chosenMailData">
<div class="mailInfo">
<h1 data-bind="text: subject"></h1>
<p>
<label>From</label>:
<span data-bind="text: from"></span>
</p>
<p>
<label>To</label>:
<span data-bind="text: to"></span>
</p>
<p>
<label>Date</label>:
<span data-bind="text: date"></span>
</p>
</div>
<!-- htmlバインディングの使用に注目してください。これにより、
メールコンテンツの改行やHTMLマークアップを画面上に表示することができます -->
<p class="message" data-bind="html: messageContent" />
</div>
<script src="./jquery.min.js"></script>
<script src="./sammy-latest.min.js"></script>
<script src="./knockout-3.4.0.js"></script>
<script>
function WebMailViewModel() {
// Data
var self = this;
self.folders = ['index', 'Archive', 'Sent', 'Spam'];
self.chosenFolderId = ko.observable();
// step2
// メールグリッドと紐付ける
self.chosenFolderData = ko.observable();
// step3
// メールデータと紐付ける
self.chosenMailData = ko.observable();
// ビヘイビア
// フォルダの内容を表示
// step4でSammy.jsを使用するため削除
// self.goToFolder = function(folder) {
// // folderの中身:'index', 'Archive', 'Sent', 'Spam'のクリックされたやつ
// self.chosenFolderId(folder)
// // step3
// // メールの表示を停止する
// self.chosenMailData(null);
// // step2
// // jQueryが必要
// // ユーザーがフォルダに移動するたびに、Ajaxリクエストを実行してselectedFolderDataにデータを設定します。
// // nullが設定された場合は非表示になる。
// $.get('/mail', {
// folder: folder
// }, self.chosenFolderData);
// };
//step4 sammyjs化
self.goToFolder = function(folder) {
// urlの末尾に#folder名を追加する
// location.hashはJSの標準
location.hash = folder;
}
// メールの内容を表示
// step4でSammy.jsを使用するため削除
// self.goToMail = function(mail) {
// // 該当のフォルダを選択状態にする
// self.chosenFolderId(mail.folder);
// // フォルダの表示を停止する
// self.chosenFolderId(null);
// // ajaxでメールの内容を取得して表示する
// $.get('/mail', {
// mailId: mail.id
// },
// self.chosenMailData);
// }
// step4 sammyjs化
self.goToMail = function(mail) {
location.hash = mail.folder + '/' + mail.id;
}
// step2
// Inboxをデフォルト表示
// step4で削除
// #付きのURLで外部からアクセスした際に、Inboxにリダイレクトされてしまうため。
// かわりにSammy内で処理する
// self.goToFolder('Inbox');
// step4
// Sammy.jsを使ってクライアントサイドでルーティング
Sammy(function() {
// フォルダの内容表示
this.get('#:folder', function() {
//フォルダに移動
self.chosenFolderId(this.params.folder);
// メールの内容を非表示に
self.chosenMailData(null)
// Ajaxでデータ取得
$.get("/mail", {
mailId: this.params.mailId
}, self.chosenFolderData);
});
// メールの内容表示
this.get("#:folder/:mailId", function() {
// メールの内容に移動
self.chosenFolderId(this.params.folder);
// フォルダの内容を非表示に
self.chosenFolderData(null);
// Ajaxでデータ取得
$.get("/mail", {
mailId: this.params.mailId
}, self.chosenMailData);
});
//初期表示
this.get('', function() {
this.app.RunRoute('get', '#Inbox')
});
}).run();
}
ko.applyBindings(new WebMailViewModel());
</script>
残る2つのチュートリアルはまた後日。