DOM:element.addEventListener
出典: MDC
目次 |
[編集] 概要
addEventListener は、イベントターゲットにイベントリスナーを登録します。イベントターゲットは、ドキュメント上のノード、ドキュメント自身、ウィンドウ、あるいは、XMLHttpRequest です。
[編集] 構文
target.addEventListener(type, listener, useCapture);
- type
- リスニングするイベントタイプを表す文字列。
- listener
- 指定されたタイプのイベントが発生するときに通知を受け取るオブジェクト。これは、
EventListenerインターフェースで実装されたオブジェクト、あるいは、単純に、JavaScript の 関数でなければなりません。
- useCapture
-
trueの場合、useCaptureは、ユーザがキャプチャを開始したいことを示しています。キャプチャの開始後、指定されたタイプのイベントの全てが、まず、登録されたlistenerにディスパッチされ、その後、DOM ツリーにおいてその下に位置する任意のEventTargetにディスパッチされます。ツリーをたどって上方へバブリングするイベントは、キャプチャを用いるように指定されたリスナーを誘発することはありません。詳細な説明は、DOM Level 3 Events を参照していください。
[編集] 例
<html>
<head>
<title>DOM Event Example</title>
<style type="text/css">
#t { border: 1px solid red }
#t1 { background-color: pink; }
</style>
<script type="text/javascript">
// t2 の内容を変更する関数
function modifyText() {
var t2 = document.getElementById("t2");
t2.firstChild.nodeValue = "three";
}
// t にイベントリスナーを追加する関数
function load() {
var el = document.getElementById("t");
el.addEventListener("click", modifyText, false);
}
</script>
</head>
<body onload="load();">
<table id="t">
<tr><td id="t1">one</td></tr>
<tr><td id="t2">two</td></tr>
</table>
</body>
</html>
上記の例では、modifyText() が addEventListener() を用いて登録された click イベントのリスナーになっています。table 中のどこをクリックしても、そのハンドラまでバブルアップし、modifyText() が実行されます。
[編集] 注記
[編集] なぜ、addEventListener を使うのですか?
addEventListener は、W3C DOM で仕様化された、イベントリスナーを登録するための方法です。その利点は以下の通りです。
- イベントに 1 つ以上のハンドラを追加することができます。これは、特に、他のライブラリ/拡張で利用しても上手く動作する必要がある DHTML ライブラリや Mozilla の拡張 のために役立ちます。
- リスナーが活性化されたときに、その動きを細かくコントールすることを可能にします(キャプチャリング 対 バブリング)。
- HTML 要素だけでなく、任意の DOM 要素 で動作します。
もうひとつの方法である、イベントリスナーを登録するための古い方法 は、後で説明します。
[編集] イベントディスパッチ中のリスナーの追加
EventListener が、イベント処理中に EventTarget に追加された場合、それが現在のアクションによって実行されることはありませんが、バブリングフェーズのように、イベントフローの後の段階中に実行されるかもしれません。
[編集] 複数の同一のイベントリスナー
複数の同一の EventListener が、同じ EventTarget に同じ引数で登録された場合、重複するインスタンスは反映されません。EventListener が 2 度呼び出されることはなく、重複するインスタンスは反映されないので、removeEventListener で手動で削除する必要はありません。
[編集] ハンドラ内での this の値
一連の類似した要素に対して一般的なハンドラを用いたいというような、イベントハンドラが実行される要素を参照したいということがたびたびあります。addEventListener() に渡す関数で this という値を用いるようにすることで、そのように変更することができます。this の値は、呼び出し元から関数に渡されることに注意してください。
上記の例では、クリックイベントから呼び出されたときの modifyText() 内の this の値は、table 't' へのリファレンスです。これは、HTML ソースに追加された場合に起こる振る舞いとは異なります。:
<table id="t" onclick="modifyText();"> . . .
onclick イベントで呼び出されたときの modifyText() 内の this の値は、グローバル(window)オブジェクトへのリファレンスになります。
[編集] Internet Explorer
IE では、標準の addEventListener ではなく、 attachEvent を使わなければなりません。IE をサポートするためには、上記の例を以下のように修正しなけれなりません。
if (el.addEventListener){
el.addEventListener('click', modifyText, false);
} else if (el.attachEvent){
el.attachEvent('onclick', modifyText);
}
[編集] イベントリスナーを登録するための古い方法
addEventListener() は、DOM 2 Events 仕様で導入されました。それ以前は、イベントリスナーを以下のように登録していました。
// 関数へのリファレンスを利用する方法—'()' が無いことに注意していください
el.onclick = modifyText;
// 関数式を利用する方法
element.onclick = function(){
...文...
};
このメソッドは、要素上に click イベントリスナーが既に存在する場合、それを置き換えます。他のイベント、blur (onblur)、keypress (onkeypress)、などのような関連するイベントハンドラも同様です。
これは、本質的には、DOM 0 の一部分なので、この方法は、非常に広くサポートされており、特別なクロスブラウザコードも必要ありません。それ故、addEventListener() の独自の機能が必要でない場合に、動的にイベントリスナーを登録する方法として普通に使われています。
[編集] メモリに関する問題
メモリ使用量が増大する問題を引き起こす方法に共通していることは、オブジェクトのメソッドをコールバックとして渡すことです。
setTimeout(obj.func, 1000); // |this| が間違って設定される!
document.addEventListener("load", obj.func, false); // |this| が間違って設定される!
単純な回避策としては、無名関数をコールバックとして渡す方法があります。
document.addEventListener("load", function(event) { obj.func(event); }, false);
注意すべきなのは、この無名関数はそれを内包する環境にある全ての変数にアクセスすることができ、それらの変数が使用するメモリは、その無名関数が使われる可能性がある限りは (つまりイベントリスナが登録されている限りは) JavaScript エンジンによって解放されないということです。この関数に対して維持される必要があるのは実際には obj だけなのに、JavaScript エンジンは他の変数も維持する事を選択し、その結果メモリの負荷が増大します。removeEventListener を呼び出すか無名関数への参照を全て削除すれば、変数の消費するメモリが解放されるようになります。なので忘れずにそれを行ない、使用されていないメモリが JavaScript エンジンによって効率的に解放されるようにして下さい。