An diesem Setup ist nichts auszusetzen (oder gibt es das?), Aber kann ich es ein wenig glätten?
Verwenden Sie stattdessen die Ereignisdelegierung. Dort suchen Sie tatsächlich nach dem Ereignis in einem Container, der nicht verschwindet, und verwenden dann event.target
(oder event.srcElement
im Internet Explorer), um herauszufinden, wo das Ereignis tatsächlich aufgetreten ist, und es korrekt zu behandeln.
Auf diese Weise hängen Sie die Handler nur einmal an und sie funktionieren auch dann weiter, wenn Sie Inhalte austauschen.
Hier ist ein Beispiel für die Ereignisdelegierung ohne Verwendung von Hilfsbibliotheken:
(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);
}
})();
Live Beispiel
Beachten Sie, dass beim Klicken auf die Nachrichten, die dynamisch zur Seite hinzugefügt werden, Ihr Klick registriert und verarbeitet wird, obwohl kein Code zum Verknüpfen von Ereignissen mit den neu hinzugefügten Absätzen vorhanden ist. Beachten Sie auch, dass Ihre Handler nur Einträge in einer Karte sind und Sie einen Handler auf dem haben document.body
, der den gesamten Versand erledigt. Nun, Sie wurzeln dies wahrscheinlich in etwas gezielterem als document.body
, aber Sie bekommen die Idee. Im obigen Abschnitt versenden wir grundsätzlich nach id
, aber Sie können das Matching so komplex oder einfach durchführen, wie Sie möchten.
Moderne JavaScript-Bibliotheken wie jQuery , Prototype , YUI , Closure oder eine von mehreren anderen sollten Funktionen zur Ereignisdelegierung bieten, um Browserunterschiede auszugleichen und Randfälle sauber zu behandeln. jQuery bietet sowohl seine live
als auch seine delegate
Funktionen, mit denen Sie Handler mit einer ganzen Reihe von CSS3-Selektoren (und noch einige mehr) angeben können.
Hier ist zum Beispiel der entsprechende Code, der jQuery verwendet (außer ich bin sicher, dass jQuery Randfälle behandelt, die in der obigen Rohversion ohne Manschette nicht behandelt werden):
(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);
Live-Kopie