かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

WinJSでのクラスの定義とWinJSでバインド可能なクラスの定義方法

WinJSには、クラスを定義するための関数があります。WinJS.Class.defineがそれです。

Personクラスの定義

WinJS.Class.define関数は、第一引数にコンストラクタを渡して、第二引数にインスタンスメソッドを渡して、第三引数にスタティックメソッドを渡します。

今回はPersonクラスでnameとageプロパティを持っていて、自己紹介をコンソールに吐き出すpresentationメソッドを持った感じで定義したいと思います。

var Person = WinJS.Class.define(
    function (name, age) {
        this.name = name;
        this.age = age;
    }, {
        presentation: function () {
            console.log(this.name + ", " + this.age);
        }
    });

これで以下のように使うことができます。

var p = new Person("tanaka", 10);
p.presentation(); // tanaka, 10

変更通知機能を追加

WinJSでは、変更通知機能をクラスに追加することができます。WinJS.Class.mix関数とWinJS.Binding.mixin関数とWinJS.Binding.expandProperties関数を使って以下のように書きます。

var Person = WinJS.Class.define(
    function (name, age) {
        this._initObservable(); // これも追加
        this.name = name;
        this.age = age;
    }, {
        presentation: function () {
            console.log(this.name + ", " + this.age);
        }
    });
WinJS.Class.mix(Person,
    WinJS.Binding.mixin,
    WinJS.Binding.expandProperties({ name: "", age: "" }));

expandPropertiesに変更通知の機能を追加するプロパティを表すオブジェクトを渡してやります。

こうすると、以下のようにbindメソッドでプロパティの変更通知を監視できるようになります。

var person = new Person("tanaka", 10);
// bindメソッドでプロパティの変更を受け取れる
person.bind("name", function (name) { console.log("name changed!!: " + name); });
person.bind("age", function (age) { console.log("age changed!!: " + age); });

データバインドできる

変更通知機能つきになったPersonクラスはさくっと双方向バインドできます。HTML全体を載せておきます。動作結果はWinJS.Binding.asを使ったときと同じです。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>WinJS Hello world</title>
    <link href="WinJS/css/ui-dark.css" rel="stylesheet" />
    <script src="WinJS/js/base.js"></script>
    <script src="WinJS/js/ui.js"></script>
    <script src="WinJS/js/WinJS.js"></script>
    <script type="text/javascript">
        (function () {
            "use strict";

            WinJS.Application.onready = function () {
                var Person = WinJS.Class.define(
                    function (name, age) {
                        this._initObservable(); // これも追加
                        this.name = name;
                        this.age = age;
                    }, {
                        presentation: function () {
                            console.log(this.name + ", " + this.age);
                        }
                    });
                WinJS.Class.mix(Person,
                    WinJS.Binding.mixin,
                    WinJS.Binding.expandProperties({ name: "", age: "" }));
                    

                var person = new Person("tanaka", 10);
                // bindメソッドでプロパティの変更を受け取れる
                person.bind("name", function (name) { console.log("name changed!!: " + name); });
                person.bind("age", function (age) { console.log("age changed!!: " + age); });
                // メソッド呼べる
                person.presentation();
                // バインド
                WinJS.Binding.processAll(document.body, person);

                // 双方向バインド
                document.querySelector("#nameInput").onchange = function (e) {
                    person.name = e.target.value;
                };
                document.querySelector("#ageInput").onchange = function (e) {
                    person.age = e.target.value;
                };

                WinJS.UI.processAll();
            };
            WinJS.Application.start();
        })();
    </script>
    <style type="text/css">
        #container {
            margin: 10px;
        }
    </style>
</head>
<body>
    <div id="container">
        <h1>Data Binding</h1>
        <div id="inputForm">
            <input id="nameInput" type="text" data-win-bind="value: name" />
            <input id="ageInput" type="text" data-win-bind="value: age"/>
        </div>
        <div id="personDiv" class="win-type-x-large">
            <span id="nameSpan" data-win-bind="innerHTML: name"></span>
            さん
            <span id="ageSpan" data-win-bind="innerHTML: age"></span></div>
    </div>
</body>
</html>