かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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>