CHAPTER6:Events
久しぶりにResig本読んだ。
Javascriptのイベントの仕組みについては十分理解していたつもりだけど、意外といろいろ新しい発見があった。
Javascriptのイベントについて
Javascriptではスレッドが1つしかない。
なので、ある処理を実行している間に発生したイベントはその処理が完了するまで待たされる。
イベントの伝達
そのイベントには「キャプチャリング」というフェーズと「バブリング」というフェーズがある。
以下のようなHTMLが合った場合に<a>でイベントが発生したとする。そうすると、イベントは<body>, <div>, <ul>, ... と上位のノードから下位のノードに伝達され最終的に<a>まで伝わる。これが「キャプチャリング」のフェーズ。
<body> <div> <ul> <li> <a href="#">.... </a>
<a>でのイベントハンドラの処理が行われた後は、今度は逆に<li>, <ul>, ... <body>という順番にイベントハンドラが呼び出される。これが「バブリング」のフェーズ。
Event
オブジェクトについて
以下のようなイディオムで両方に対応できる。
hoge.onkeypress = function(e) { e = e || window.event; alert(e.keyCode); }
イベントハンドラ内でのthis
について
イベントハンドラ内でthisを参照すると、そのイベントが発生した要素(オブジェクト)を参照することが出来て便利。ただし、IEにおいて、イベントハンドラの定義方法によってはthisの扱いが異なるので注意する必要あり。(後述)
ブラウザのデフォルトの動作をオーバーライドする
ブラウザでイベントが発生したとき、以下のような順番で処理が行われていく。
- キャプチャリング
- バブリング
- ブラウザのデフォルトの動作
なので、バブリングの途中でイベントの伝達を止めてしまえば、そのイベントに対するブラウザのデフォルトの動作は発生しなくなる。
その方法はW3C標準とIEとで異なる。(eはイベントハンドラに渡されたeventオブジェクトとする)
// e is evetn object // W3C e.preventDefault(); // IE only window.event.returnValue = false;
イベントを割り当てる3つの方法
古典的な方法
'on〜'というプロパティを使う。
hoge.onclick = function(e) { ... };
利点:
- ほとんどのブラウザでサポートされている
this
キーワードでその要素自身を参照することができる。
欠点:
- イベントのバブリングにしか対応しておらず、キャプチャリングの制御ができない。
- 1つしかハンドラを登録できない。
W3C標準
addEventListener()
メソッドを使う。
hoge.addEventListener('click', function(e) { ... }, false);
利点:
- キャプチャリングとバブリングをサポートしている。
- 1つの要素に複数のイベントハンドラを登録することができる。
this
キーワードでその要素自身を参照することができる。
欠点:
- IEでサポートされていない。
IE固有の方法
attachEvent()
メソッドを使う。
hoge.attachEvent('onclick', function() { ... });
利点:
- 1つの要素に複数のイベントハンドラを登録することができる。
欠点:
- IEしか対応していない。
this
がwindowオブジェクトを参照していて混乱の元。- イベントのバブリングにしか対応しておらず、キャプチャリングの制御ができない。
解決策
Dean Edwards さんという人が書いたaddEvent()
を使えば解決すると言ってる。
以下のリンク参照:
Dean Edwards: addEvent() - My Solution
ほかに気をつけること
- domオブジェクトが参照できることをチェックする。例)
if ( document && document.getElementById )
- タグの属性にコードを埋め込まない。ダメな例)
<a href="#" onclick="doHoge()">
- javascriptが無効になっていてもナビゲートできる作りにする