prototype.jsで綺麗なコードを書く
hawkさんにかなり助けてもらいつつ、コードが綺麗になってきたのでまとめてみる。
Ajaxイン・アクションの復習も兼ねて。
理解できてくると段々楽しくなってくるね。ブラウザの挙動の違いは困るけどprototype.jsが結構吸収してくれてるぽい。
HTMLからJavaScriptのコードを取り除く
知っている人は何を今更と思うかもしれないが、他の言語をやっていてJavaScriptに手を出そうとしたときに気付きにくい。入門書ではほとんどHTMLのタグの中に書いてるんだもの。
Event.observe(window, 'load', function(){ // 初期化処理 Initializer.initLink(); Initializer.initForm(); });
ネットでもbodyタグにonload=hoge() としている例が沢山あるがそれは好ましくない。JavaScriptを外部ファイルにしきれていないのでちゃんと分ける。
オブジェクト指向で書く
上の例だと
var Initializer = { initLink: function(){ }, initForm: function(){ } }
のようなオブジェクトを定義しておいて名前空間を分ける。
または、
function Initializer(){ this.initLink(); this.initForm(); } Initializer.prototype.initLink = function(){ } Initializer.prototype.initForm = function(){ } Event.observe(window, 'load', function(){ var initializer = new Initializer(); });
でも良い。こちらはオブジェクトを複数扱ったり状態を保持したいとき向け。
イベントハンドラはリスナに登録する
汎用的にするには、onclick等に直接書かずにイベントリスナにハンドラ関数を登録する。
var Initializer = { initLink: function(){ Event.observe('ajaxtext', 'click', function(){ // Ajaxでリンク先を表示したりとか }); }, initForm: function(){ Event.observe('form', 'submit', (function(e){ if (this.checkFormError()){ // 入力のエラーなど $('errorMessage').innerHTML = 'error!'; Event.stop(e); } }).bind(this)); }, initInfo: function(menuItem){ Event.observe(menuItem, 'click', this.viewInformation.bind($(menuItem))); }, checkFormError: function(){...}, viewInformation: function(){...} }
イベントを登録するにはbindAsEventListener()の方が適しているようだが
http://blog.hawklab.jp/item-62.html
Event.observe()を使うならば必要ないっぽい。実際 bindAsEventListener()内で event||window.event としているだけだった。
$('form').onclick = this.myFunc.bindAsEventListener(this, arg1, arg2);
とobserveを使わない場合には有効だが、こっちを使う必要はなさそう。bind()のソースは$A(arguments)とかやっていてbindAsEventListener()の方はやってないのだが、この違いはまだ理解できていない。
# 追記
# なんか複数の引数(arg1, arg2)を受け取れなかった・・イベントだから引数はeventのみ?
イベントリスナは複数登録できる。onclickに対する動作を一カ所にまとめて書かなくてもいいようになる。
実行される順番は・・・不定だったような。実行される順番はIEのattachEventとaddEventListenerで逆(?)なので、複数登録する場合は互いに独立した関数にする。