HTML5準拠
従来のDojoで宣言的な方法でHTMLを作成する場合、以下の例のように本来のHTMLには存在しない属性(dojoType、djConfig、dojoAttachPoint、dojoAttachEvent、各モジュールのプロパティなど)を独自属性として利用していました。
<script src="dojo.js" djConfig="parseOnLoad: true, isDebug: true"></script> <div dojoType="dijit.layout.BorderContainer"> <div dojoType="dijit.layout.ContentPane" region="top" gutters="true"> ...
HTML5ではこういった独自属性はdata-XXXという形式を使うように決められているため、Dojo 1.6ではこれに準拠した記法が推奨されています。
旧表記 | 新表記 |
djConfig | data-dojo-config |
dojoType | data-dojo-type |
dojoAttachPoint | data-dojo-attach-point |
dojoAttachEvent | data-dojo-attach-event |
その他のプロパティ | data-dojo-propsに文字列としてkey:value形式で記述 |
<script src="dojo.js" data-dojo-config="parseOnLoad: true, isDebug: true"></script> <div data-dojo-type="dijit.layout.BorderContainer"> <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top', gutters: true"> ...
同様にウィジェットのテンプレート内での記法も以下のようになります。
<div dojoAttachpoint="headerNode"> <div dojoType="dijit.form.Button" dojoAttachEvent="onclick: _doSomething"> ...
<div data-dojo-attach-point="headerNode"> <div data-dojo-type="dijit.form.Button" data-dojo-attach-event="onclick: _doSomething"> ...
ただし互換性維持のため、少なくともDojo 1.7では従来の記法も動作します。
dojo.Statefulとwatch()
Dojo 1.5からコア・ライブラリにdojo.Statefulが導入され、Dojo 1.6から本格的に採用されています。dojo.Statefulはプロパティを持つあらゆるオブジェクトのベースとなるクラスで、get()、set()、watch()関数を持ちます。get()はプロパティのgetter、set()はプロパティのsetter、watch()はプロパティの変更を監視し、値が変更された時の処理を指定する関数です。以下のように使用します。
dojo.require("dojo.Stateful"); var obj = new dojo.Stateful(); // 監視の開始 var handle = obj.watch("foo", function(name, oldValue, newValue){ console.log("プロパティ " + name + " が " + newValue + " に変更されました "); }); // 単独のプロパティのセット // "プロパティfooがbarに変更されました"と表示 obj.set("foo", "bar"); // オブジェクトによるセット // 以下は obj.set("foo", "Howdy"); obj.set("bar", 3); と同等 obj.set({ foo: "Howdy", bar: 3 }); // setはカスケードが可能 // 以下はobj.set("foo", "Howdy"); obj.set("bar", 3); と同等 obj.set("foo", "Howdy").set("bar", 3); // 監視の終了 handle.unwatch(); // なにも表示されない obj.set("foo", "HOGE");
Dojo 1.6ではこのdojo.Statefulがウィジェットのベースクラス(次章で説明する_WidgetBaseの親クラス)となっており、上記の仕組みは全てのウィジェットに対して暗黙的に使用できます。以下に例を示します。
dojo.require("dijit.form.TextBox"); var tb = new dijit.form.TextBox().placeAt(dojo.body()); tb.watch("value", function(name, oldValue, newValue){ console.log("プロパティ " + name + " が " + newValue + " に変更されました "); });
watch()で登録されるコールバック関数は内部的にスタックされます。つまり、プロパティの変更の度に登録されたコールバック関数が全て呼び出されるので、意図せず複数回登録されないように配慮する必要があります。例えば、カスタム・ウィジェットの場合は、ライフサイクル上で1度しか呼ばれないpostCreateのようなメソッドで呼ぶといった方法が考えられます。
また、このスタックは自動的にはdestroyされないので、メモリリークを避けるため、不要になったら明示的にunwatchする必要があります。カスタム・ウィジェットの例を以下に示します。
dojo.declare("my.custom.TextBox"... ... _watchHandler: null; // postCreateでまとめてwatch() postCreate: function(){ ... // 配列にwatch用ハンドルを保持する this._watchHandler = []; this._watchHandler.push( this.watch("prop1", function() {...}); ); this._watchHandler.push( this.watch("prop2", function() {...}); ); } ... // destroyでまとめてunwatch() destroy: function(){ ... dojo.forEach(this._watchHandler, function(h){ h.unwatch(); }); }