AMD APIを使ったDojoアプリケーションの書き方
AMD APIのDojoへの投入はDojo 2.0を見越したものなので、Dojo 1.7では今までのdojo.require()やdojo.provide()などに対する互換性が保たれています。
ですが最初にお話ししたようにAMD APIには数多くのメリットがありますので、1.7から新しくDojoを使い始める場合や、新しいDojoを使うプロジェクトにはAMD APIを使うのがよいでしょう。また今まで書かれたDojoプロジェクトをAMD APIで書き換えることにも大きなメリットがあります。ここではAMD APIを使ったDojoアプリケーションの書き方などについて触れてみます。
Dojo 1.7のdojo.require()は、AMD APIで書かれたモジュールも以前の形式で書かれたモジュールもロードすることができます。
モジュールの定義、連鎖依存関係の記述およびモジュールの遅延ロード
これまで説明した内容から想像されるかと思いますが、モジュールの定義(今までのdojo.provide()にあたります)はAMD APIのdefine()関数で行うことができます。define()関数の説明でも紹介しましたが、define()関数は同時にモジュールの連鎖依存関係も定義することができます(これは今までモジュールの最初に書かれていたdojo.require()に相当します)。
今までモジュールの最初以外の部分に書かれていたdojo.require(),つまり一般的なモジュールの遅延ロードはrequire()関数で行うことができます。
今までXDローダー(こちらで触れています)で使っていたdojo.addOnLoad()で非同期なモジュールのロードを待つことはAMD APIではきれいな形で行うことができます。例えば今まではXDローダーを使った非同期なモジュールのロードは次のように行っていましたが:
dojo.require("my.DatePicker"); dojo.addOnLoad(function(){ var picker = new my.DatePicker; … });
AMDローダー(require() API)を使うと次のようにとてもシンプルです:
require(["my/DatePicker"], function(DatePicker){ var picker = new DatePicker; … });
ここでmy/DatePickerにはmy.DatePickerに相当するクラスがモジュールとして定義されているものとします。
上の2つの例から分かる通り、dojo.addOnLoad()を使った場合、どのモジュールが読み込まれたときにどのコードを呼ぶということを明示的に指定することができませんが、require()関数ではこれを明示的に行うことができます。
一般のカスタムウィジェット
Dojo 1.7以前でカスタムウィジェットを作るときは、dojo.declare()関数を使い、dijit._Widgetを継承したクラスを作るのが一般的でした。Dojo 1.7以降でも基本は変わりませんが、AMD APIを使って次のように書くことができます:
define([ "dojo/_base/declare", "dijit/_WidgetBase" ], function(declare, _WidgetBase){ return declare("my.Widget", _WidgetBase, { // ウィジェットの実装を書いていく... }); });
ここで、dijit/_WidgetBaseはDojo 1.6で導入された最小セット版のウィジェットのベースクラスです。dojox.mobileでよく使われ、機能に制限はありますがデスクトップ用のウィジェットにも使うことができます。
テンプレートウィジェット
DojoにはウィジェットのUIを構成するHTMLをコードとは別な場所に定義する機能(テンプレート)があります(こちらで触れています)。テンプレートウィジェットを作るとき、Dojo 1.7以前ではdijit._Templatedを継承し、さらにtemplatedStringプロパティにdojo.cache()関数の返り値をセットしていましたが、Dojo 1.7以降ではAMD APIを使って次のように作ることができます(Dojo 1.7では以前のdojo.cache()を使ったやり方もサポートされています):
define([ "dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/text!my/template.html" ], function(declare, _WidgetBase, _TemplatedMixin, template){ return declare("my.TemplatedWidget", [_WidgetBase, _TemplatedMixin], { // テンプレートの指定 templateString: template, // ウィジェットの実装を書いていく... … }); });
先ほども少し触れましたが、dojo/textは任意のテキストファイルを読み込むことができるAMDローダープラグインで、ここではテンプレートのHTMLを読み込んでいます。
dijit/_TemplatedMixinは1.7で導入された最小セットのテンプレートウィジェットのベースクラスです。テンプレートの中にウィジェットを定義する機能が省かれており、この機能を使う場合はさらにdijit/_WidgetsInTemplateMixinも継承する必要があります。
国際化
言語依存のメッセージをDojoウィジェットやDojoアプリケーションで使う場合、Dojo 1.7以前ではdojo.getLocalization()関数を使っていました。Dojo 1.7でもdojo.getLocalization()関数は使われていますが、AMDローダープラグインのdojo/i18nを使うと次のようにもっとシンプルになります:
define([ "dojo/_base/declare", "dojo/_base/lang", "dijit/_WidgetBase", "dojo/i18n!./nls/messages" ], function(declare, lang, _WidgetBase, messages){ return declare("my.Widget", _WidgetBase, { postMixInProperties: function(){ this.inherited(arguments); // メッセージをウィジェットのプロパティとすることにより // テンプレートなどからのアクセスを簡便化 lang.mixin(this, messages); }, // ウィジェットの実装を書いていく... … }); });