今回は、Sencha Ext JSのイベントについて見て見ましょう。
JavaScriptで物を作っている人、それ以外でも何かしらのイベントが起きて、それに対して処理を書く、ということに慣れている人は多いのでは無いでしょうか。プログラマーが、何かしらの関数を呼び出して処理を行う、1対1の関係ではなく、イベントが起きて、そこのイベントに登録されている関数オブジェクトが次々実行されていく、1対多の関係がイベント制御の基本になります。
「え?別に関数呼び出せばいいじゃん」
っていう人もいます、ええ、実際います…。いや、動くんですけど、柔軟性が欠けることは請け合いです。
「例えば、ボタンを押したら、画面上のパネルのタイトルを全部書き換える」
なんてことを考えたときに、ボタンが押された時の処理で、すべてのパネルオブジェクトを把握・取得している必要がありますよね?これ、パネル1個増えたりする度に、毎回書き換えるんですかね?書き換えるしかないですよね。
「ボタンから見て、パネルを制御する」
のではなく、
「パネルから見て、ボタンが押されたら」
という考え方で処理を行う事で、ボタン側は、押された時の処理内容を把握する必要はありません。あくまでイベントを発火(発生)させるだけで、イベントに登録されている関数オブジェクトが自動的に呼び出されれば、後はそれぞれのパネルなりなんなり、イベントを監視している側(リスナー)で処理を記述すればよいのです。ゲームとか作るときでも、この形(オブザーバーパターン)で実装することが多いでしょう。Flashでも複雑なインタラクティブコンテンツを作るときには、オブザーバーパターンで作るとスッキリ書けたし、じゃないと死ぬな的なことを思った記憶があります。
さて、Sencha Ext JSでは、2種類のイベントを制御します。1つは、DOMイベント、もう1つは、Sencha Ext JS内で制御されるExt イベントです。このDOMイベントとExtイベントがごっちゃになると、わけわかめなので、とりあえずそれぞれの違いを見ていきましょう。
DOMイベント
DOMイベント、DOM… ドム.. なんかやだなぁ〜みたいなイメージありますかね。HTMLベースのアプリケーションを構築していて、結局はDOMを制御してタグを動的に作ったり変更したり、消したりしてアプリケーションを作っていくのは、Sencha Ext JSに限ったことではありません。そして、逃れることもできません。
まず、ここでは、DOM=タグとして説明します。DOM=DOM APIって話をし出すとわけわかんなくなるんで。さて、用はするにタグです、DIVとか、Pとか、アレです。DIVタグがクリックされたら、clickイベントが起きます、まぁIEの時onClickですか。まぁいいです、クリックされたイベントが起きるんです。このときに何かしらの処理をする関数オブジェクトを設定することをイベントリスナーの登録といいます。
「ああ、それ知ってるよ!onClickでしょ!」
はいはい、昔懐かし、onClick。
1 2 3 |
<div id="hoge" onClick="xxxxxx"> </div> |
こんな1行にJavaScript書くのかよ!っていう見るだけで、嫌な記憶がよみがえる人も多いのでは。
「いやいや、document.getElementByIdで取得すれば、もうちょいマシよ。」
DOM APIですね、getElementById、コレ使って捕まえてから処理を設定することもできますが、先ほどちらっと出てきたように、IEとそれ以外でイベントリスナーの登録方法が若干違ったりします。
「いや、そこはjQueryでだな…」
そこまで解ってるなら、おんなじ様なもんです。Sencha Ext JSでDOMオブジェクトを取得する方法はいくつかあるのですが
1 |
var hogeDiv = Ext.get('hoge'); |
で取得できます。
「ん〜書き方違うだけで、getElementByIdとかわんなくね?」
いや、違うんです、DOMオブジェクトを直接取得しているわけではなく、DOMオブジェクトをラッピングしたSencha Ext JSのクラスオブジェクトが返されます。DOMオブジェクトを参照したい場合は、以下の様にアクセスします。
1 |
var hogeDiv = Ext.get('hoge').dom; |
そして、このラッピングされたオブジェクトを使ってイベントリスナーを登録することができます。
1 2 3 |
Ext.get('hoge').on('click', function() { // クリックされたときの処理 }); |
このように、DOMオブジェクトを参照して、イベントに対して処理を追加していく事ができます。
先ほどラッピングしたオブジェクトと言いましたが、Ext.dom.Elementクラスの事です。
Ext.get意外にも、Ext.fly/Ext.selectなどIDを指定して取得する方法以外に、存在するdivタグ全てを取得するとか、このDOMオブジェクトの子供の中のPタグ全部を引っ張るとか、そういった使い方ができます。Ext.dom.Elementを使った制御方法も、深いのでどっかでじっくりやりたいですね。感覚的には、jQueryでDOM制御を行うのと同じような感じかもしれません。そして、何よりSencha Ext JSの複雑なUIを作り上げているのも、このExt.dom.Elementクラスを通じて構築されているということなのです。
ま、DOMイベントはこれくらいにして。
Ext イベント
さて、DOMイベントとは別に、Extイベントを見ていきましょう。そもそも、それ何?って感じですよね。ExtイベントはDOMイベントとは別に、Sencha Ext JSが発行するイベントです。Sencha Ext JSの中に、Ext.mixin.Observable というクラスがあり、こいつがイベント機能を担っています。
Sencha Ext JSでは、イベントを発生されることを、イベント発火といい、fireEventというメソッドを通じて実行されます。fireEventされたときに、何かしらの処理を登録しておいて実行してほしい!というときには、on/addListener、登録したけど、やめたい外したい時には、un/removeListenerを使います。
listenersを使ってイベントリスナーを追加する
まぁ、コンポーネントオブジェクトを捕まえて、イベントを追加するのであれば、on/unでよいのですが、コンフィグオプションで登録するときは、どうするのでしょうか?そのためにlistenersというのが用意されています。
1 2 3 4 5 6 7 8 9 |
items: [{ xtype: 'button', text: '押してみろ', listeners: { click: function(button) { alert('押されたぜ'); } } }] |
こんな感じです。listenersのキーがイベント名、そして、その値に関数オブジェクトを指定します。
「あれ?ボタンってhandlerでやってなかった?」
はい、やってました。
1 2 3 4 5 6 7 |
items: [{ xtype: 'button', text: '押してみろ', handler: function(button) { alert('押されたぜ'); } }] |
handlerは、内部的にボタンオブジェクトに対して、clickイベントに対してhandlerに設定された関数オブジェクトを自動的に登録してくれる設定になります。
終わりに
今回は、DOMイベント、Extイベントの違いを軽く見て見ました。いや、正直イベント制御も結構多機能なので、軽くしておかないとすんごいイベントだけで時間がかかってしまいます。ちなみに、Ext.mixin.Observable(旧 Ext.util.Observable)も地味に進化しているので、これも一通り全体を把握したら掘り下げたい項目です。
そして、イベントリスナーは、直接関数オブジェクトを指定するだけでなく、文字列でビューコントローラのメソッド名を記述して、後はビューコントローラーに処理を記述することもできます。というか、ソッチが主流ですね、今は。
今日は、イベントって聞いただけで、嫌になる人にも、なんとなくたいそうなことではないということ、そしてその簡単な制御方法を紹介しました。イベント制御は、Sencha Ext JSのみならず、アプリケーション構築における非常に重要な項目です。是非APIドキュメントを除いて、どんなイベントがあるのかな?とか、眺めてみてください。