2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

knockout.jsチュートリアル自分用メモ

Last updated at Posted at 2018-06-17

#概要
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から返されるデータを見ることができます。

spa.html

    <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つのチュートリアルはまた後日。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?