addEventListenerでイベントリスナを追加したあとにinnerHTMLに文字列を連結するとイベントリスナは消えてしまう
まともなjavascripterにとっては当たり前なのかもしれないけどgreasemonkeyスクリプトを書く際に引っかかったのでメモ。DOM操作とinnerHTMLへの代入を混ぜて使うときの注意。
addEventListenerでDOMノードへイベントリスナを追加したあとでinnerHTMLに文字列を連結するとイベントが無効になる。・・無効になるというか、多分新しいノードが作成されてイベントが設定されたノードが破棄されるのだと思う。web上の情報ではDOMノードをappendChildするよりもinnerHTMLを直接弄ったほうが高速とあったのでそちらを使ってプログラムしていのだけれどイベントが動作してくれずに悩んだ。Ubuntu8.04のfirefox3で確認しただけので他のブラウザではどうなるか知らない。
<html> <head> <script> function $(tid){ return document.getElementById(tid); } function f() { $("container").innerHTML += "<button id='f'>push</button>"; $("f").addEventListener("click", function(){alert("f");}, true); } function g() { $("addButton").disabled = true; $("container").innerHTML += "<button id='g'>push2</button>"; $("g").addEventListener("click", function(){alert("g");}, true); } </script> </head> <body onload="f();"> <p>addEventListenerしたあとにinnerHTMLを弄る(文字列連結、代入)とイベント リスナが無効になるか?</p> <p>確認手順 <ul> <li>画面が描画されたらpushボタンを押してalertされるのを確認</li> <li>画面下にあるボタンを押してpush2ボタンを描画させる</li> <li>push2ボタンのコールバックが動作してpushボタンのコールバック>が動作しなければ予想どおり。</li> </ul> </p> <div id="container"></div> <button id="addButton" onClick="g();">add new button</button> </body> </html>
ロード直後はボタン"push"を押下でalertが出る
"add new button"ボタン押下後は"push"を押下してもalertは出ない("push2"押下ではalertが出る)。
たったこれだけのことでだいぶ時間を使ってしまった。やっぱり体系的に学ばないとこういうどうでもいいところでひっかかる。
今度オライリーのjavascript本を買ってまともに学習しよう。