2013年1月18日金曜日

knockout.jsを動かしてみたメモ


公式ドキュメントを見たほうがいいじゃない
http://knockoutjs.com/documentation/introduction.html


■インストール

VisualStudioのパッケージマネージャーコンソールで以下をタイプしてインストール
Install-Package knockoutjs



当然だけどhtmlに読み込まないと使えない

    <script src="/Scripts/knockout-2.1.0.js" type="text/javascript"></script>


■その1

observableオブジェクトの値を変えてUIも更新させてみる


<span data-bind="text: personName"></span>
<span data-bind="text: personAge"></span>
<button data-bind="click: change">変更</button>

<script type="text/javascript">

    function viewModel() {
        // observableオブジェクトセット(初期値も設定している)
        this.personName = ko.observable("hoge");
        this.personAge = ko.observable(20);

        // ボタンが押されたら変更!
        this.change = function () {
            this.personName("foo");
            this.personAge(22);
        };
    }

    // knockout.jsにview modeをバインド
    ko.applyBindings(new viewModel());

</script>



実行結果




変更ボタンを押すとテキストが変わる。それだけ。
observableオブジェクトの値を変える→UIも更新される の流れ。


■その2

foreachバインドで一覧を生成してみる

<!-- $indexで配列のインデックス値を取得できる(0始まり) -->
<!-- $parentで親のコンテキストを取得できる -->
<table>
  <tbody data-bind="foreach: people">
     <tr>
        <td>[No.<span data-bind="text: $index() + 1"></span>]</td>
        <td data-bind="text: lastName"></td>
        <td data-bind="text: firstName"></td>
        <td>
            <a href="#" data-bind="click: $parent.remove">削除</a>
        </td>
     </tr>
  </tbody>
</table>
<button data-bind="click: change">追加</button>

<script type="text/javascript">

    function viewModel() {
        var self = this;

        // observableArrayをセット(配列で初期化している)
        self.people = ko.observableArray([
            { firstName: '太郎', lastName: 'ほげ' },
            { firstName: '一郎', lastName: 'ふー' },
            { firstName: '三郎', lastName: 'ほげほげ' }
        ]);


        // 追加が押されたら要素追加!
        self.change = function () {
            self.people.push(
                { firstName: '追加分', lastName: '私は' }
            );
        };
        // 削除が押されたら要素削除!
        self.remove = function () {
            self.people.remove(this);
        };
    }

    ko.applyBindings(new viewModel());

</script>



実行結果



いろいろ詰め込みすぎた。

■その3

ko.computedで他のobservableオブジェクトが変更された時に一緒に更新

<!-- valueバインドはコントロールの入力値をview modelに反映させる事ができる -->
氏:<input type="text" data-bind="value: lastName, valueUpdate: 'afterkeydown'" />
名:<input type="text" data-bind="value: firstName, valueUpdate: 'afterkeydown'" />

<br />

<span data-bind="text: personName"></span>

<script type="text/javascript">

    function viewModel() {
        this.lastName = ko.observable('ほげ');
        this.firstName = ko.observable('太郎');
       
        // lastNameとfirstNameが更新されたらpersonNameも更新される
        this.personName = ko.computed(function () {
            return this.lastName() + " " + this.firstName();
        }, this);
    }

    ko.applyBindings(new viewModel());

</script>



実行結果



テキストボックスを編集するとリアルタイムで下のテキストも変わる


■その4

templateバインドでテンプレートを切り替える。あとforeachオプションと一緒に使ってみる。

<!-- nameでテンプレート名の指定を行っている -->

<table>
  <tbody data-bind="template: { name: 'simple-template', foreach: people }">
  </tbody>
</table>

<table>
  <tbody data-bind="template: { name: 'number-template', foreach: people }">
  </tbody>
</table>

<script type="text/html" id="simple-template">
     <tr>
        <td data-bind="text: lastName"></td>
        <td data-bind="text: firstName"></td>
     </tr>
</script>

<script type="text/html" id="number-template">
     <tr>
        <td>[No.<span data-bind="text: $index() + 1"></span>]</td>
        <td data-bind="text: lastName"></td>
        <td data-bind="text: firstName"></td>
     </tr>
</script>

<script type="text/javascript">

    function viewModel() {
        this.people = ko.observableArray([
            { firstName: '太郎', lastName: 'ほげ' },
            { firstName: '一郎', lastName: 'ふー' },
        ]);
    }

    ko.applyBindings(new viewModel());

</script>



実行結果





knockout.jsを使うとhtmlがシンプルになってイイネ!