はじめに
DojoはWebアプリケーションを開発するために必要な豊富なウィジェットを提供していますが、実際に本格的なWebアプリケーションを開発する場合、提供されているビルトインのウィジェットをそのまま利用するだけでは要件を満たせないことが多々あります。そのような場合の解決策の一つとして、カスタム・ウィジェットを自作することが考えられます。カスタム・ウィジェットを作るには、ウィジェットがどのように生成され、最終的に廃棄されるか、いわゆるライフサイクルを正しく理解しておくことが重要です。
本稿では、Dojoのウィジェット・フレームワークが定義するウィジェットのライフサイクルの中で、重要となる幾つかのメソッドを解説し、簡単なカスタム・ウィジェットを例に、具体的にどのようなプログラミングが必要になるのかを紹介します。
なお、既にDojo 1.6がリリースされており、サンプル・ファイルはDojo 1.6でも動作することは確認済みですが、本稿の内容はDojo 1.5のものとなっていることをご了承ください。必要に応じて補足を追加していますが、Dojo 1.6でライフサイクルに関しての大きな変更はありません。また、サンプル・ファイルの実行方法については、『Dojo道場 ~ 第1回「グラフを使いこなす(前編)」』を参照してください
ウィジェットを動作させるには
まずはじめに、Webブラウザ上でウィジェットを動作させる方法を簡単に解説します。ウィジェットはHTML、CSS、およびJavaScriptから成る、Webブラウザ上で動くユーザー・インターフェースの部品です。ウィジェットをWebブラウザ上で動作させるには、JavaScriptのコードで構築する(Programmatic)場合と、HTML上に宣言的に構築する(Declarative)場合の2通りがあります。
JavaScriptのコードで構築する場合はnewオペレータでオブジェクトを生成し、HTMLの特定の場所に挿入します。ウィジェット自体はJavaScriptのオブジェクトですが、ウィジェット・フレームワークがdomNodeという、その名のとおりDOMのNodeをプロパティとして自動的に生成するので、HTML内に組み込むには以下のようなコードになります。
// Buttonオブジェクトの生成 var button = new dijit.form.Button({label: "OK"}); // 生成したDOMをHTML内に追加 dojo.place(button.domNode, dojo.body()); // button.placeAt(dojo.body()) や // document.body.appendChild(button.domNode); でも可 button.startup();
HTMLとして宣言的に構築する場合は、以下のようにHTMLのタグにdojoTypeという属性を追加し、ウィジェットのクラス名を指定し、必要なプロパティはタグの属性として指定します。
<div dojoType="dijit.form.Button" label="OK"></div>
どちらの場合もウィジェットのライフサイクルに応じてウィジェットが生成されます。宣言的に構築した場合は、Dojoのパーサーがリスト1に相当するJavaScriptのコードを自動的に実行すると考えればよいです。つまりウィジェットのライフサイクルはnewオペレータで開始され、通常のJavaScriptのオブジェクトと同様、constructorメソッドから始まり、次章に示すライフサイクル・メソッドが順に実行されることになります。
Dojo 1.5以前ではdojoTypeのようにHTMLには準拠しない属性を採用していましたが、Dojo 1.6ではHTML5に準拠して、カスタム・プロパティはdata-*を使用するように変更されました。今までの表記も使うことはできますが、例えばdojoTypeはdata-dojo-type、dojoConfigはdata-dojo-config、ウィジェット固有のプロパティはprop1="value1" prop2="value2"ではなく、data-dojo-props='prop1: "value1", prop2: "value2"'のように表記することが推奨されています。
ライフサイクル・メソッド
カスタム・ウィジェットを開発する上で重要なライフサイクル・メソッドを以下に列挙します。
メソッド名 | 説明 |
constructor | 通常のJavaScriptのオブジェクトと同様のコンストラクタメソッドです。ウィジェットのもつプロパティの初期化などを行います。 |
postMixInProperties | ウィジェットのプロパティが挿入された後に実行されます。プロパティ値のバリデーションなどを行います。 |
buildRendering | ウィジェットの基本となるDOMを構築するためのメソッドであり、テンプレートの仕組みを実現するためのメソッドと言っても過言ではありません。 |
postCreate | ウィジェットの生成が終了した後に実行されます。イベント・ハンドラの定義などを行います。 |
startup | 自分自身、および、子供のウィジェットが存在する場合は全ての子供が、HTML ドキュメントに挿入された後に実行されます。 |
destroy | ウィジェットが廃棄される時に実行されます。特にIEなどで起こるメモリリークなどを避けるために必要な処理を行います。 |
上記のライフサイクル・メソッドの内、destroy以外は全てウィジェットの生成に関わるものです。constructorはオブジェクトがnewされた時点で呼び出され、postMixInProperties, buildRendering, postCreateメソッドは、全てのウィジェットのベースクラスであるdijit._Widgetのcreateメソッド(注: Dojo 1.6ではdijit._WidgetBaseのcreateメソッド)で、順に呼び出されます。startupメソッドは、そのウィジェット、および子供のウィジェットが存在する場合は全ての子どもがドキュメントに挿入された後に実行されます。
実はどの処理をどのライフサイクル・メソッド内に記述するかは、あくまで目安に過ぎません。極端なことを言うと、ほとんどの処理をpostCreate内に記述しても問題なく動く場合もありますし、実際にそのように書かれているDojo自体のコンポーネントもあります。しかし、本稿では各ライフサイクル・メソッドのもつ元々の意味や用途を鑑み、こんな時はどのメソッドを実装すればよいかという判断の基準となるような、ベストプラクティス的な解説を目指します。