この設定に問題はありません(またはありますか?)が、少しスムーズにできますか?
代わりに、イベント委任の使用を検討してください。ここで、消えないコンテナーでイベントを実際に監視し、event.target
(またはevent.srcElement
IEで)使用して、イベントが実際に発生した場所を特定し、正しく処理します。
そうすれば、ハンドラーをアタッチするのは1回だけで、コンテンツを交換してもハンドラーは機能し続けます。
ヘルパーライブラリを使用しないイベント委任の例を次に示します。
(function() {
var handlers = {};
if (document.body.addEventListener) {
document.body.addEventListener('click', handleBodyClick, false);
}
else if (document.body.attachEvent) {
document.body.attachEvent('onclick', handleBodyClick);
}
else {
document.body.onclick = handleBodyClick;
}
handlers.button1 = function() {
display("Button One clicked");
return false;
};
handlers.button2 = function() {
display("Button Two clicked");
return false;
};
handlers.outerDiv = function() {
display("Outer div clicked");
return false;
};
handlers.innerDiv1 = function() {
display("Inner div 1 clicked, not cancelling event");
};
handlers.innerDiv2 = function() {
display("Inner div 2 clicked, cancelling event");
return false;
};
function handleBodyClick(event) {
var target, handler;
event = event || window.event;
target = event.target || event.srcElement;
while (target && target !== this) {
if (target.id) {
handler = handlers[target.id];
if (handler) {
if (handler.call(this, event) === false) {
if (event.preventDefault) {
event.preventDefault();
}
return false;
}
}
}
else if (target.tagName === "P") {
display("You clicked the message '" + target.innerHTML + "'");
}
target = target.parentNode;
}
}
function display(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.body.appendChild(p);
}
})();
実例
ページに動的に追加されるメッセージをクリックすると、追加される新しい段落にイベントをフックするコードがない場合でも、クリックが登録されて処理されることに注意してください。また、ハンドラーがマップ内の単なるエントリであり、すべてのディスパッチを実行するハンドラーが1つあることにも注意してくださいdocument.body
。さて、あなたはおそらくこれをよりターゲットを絞った何かに根ざしているでしょうdocument.body
、しかしあなたはその考えを理解します。また、上記では基本的にはでディスパッチしてid
いますが、複雑なものから単純なものまで、好きなだけマッチングを行うことができます。
jQuery、Prototype、YUI、Closure、またはその他のいくつかのような最新のJavaScriptライブラリは、ブラウザの違いをスムーズにし、エッジケースをきれいに処理するためのイベント委任機能を提供する必要があります。jQueryは、その関数live
とdelegate
関数の両方で確かに機能します。これにより、CSS3セレクターの全範囲(および一部)を使用してハンドラーを指定できます。
たとえば、jQueryを使用した同等のコードは次のとおりです(jQueryがエッジケースを処理すると確信している場合を除きます)。
(function($) {
$("#button1").live('click', function() {
display("Button One clicked");
return false;
});
$("#button2").live('click', function() {
display("Button Two clicked");
return false;
});
$("#outerDiv").live('click', function() {
display("Outer div clicked");
return false;
});
$("#innerDiv1").live('click', function() {
display("Inner div 1 clicked, not cancelling event");
});
$("#innerDiv2").live('click', function() {
display("Inner div 2 clicked, cancelling event");
return false;
});
$("p").live('click', function() {
display("You clicked the message '" + this.innerHTML + "'");
});
function display(msg) {
$("<p>").html(msg).appendTo(document.body);
}
})(jQuery);
ライブコピー