Nie ma nic złego w tej konfiguracji (czy jest?), Ale czy mogę trochę wygładzić?
Zamiast tego spójrz na użycie delegowania zdarzeń. W tym miejscu faktycznie obserwujesz zdarzenie w kontenerze, który nie znika, a następnie używasz event.target(lub event.srcElementw IE), aby dowiedzieć się, gdzie zdarzenie faktycznie miało miejsce i poprawnie je obsłużyć.
W ten sposób dołączasz moduły obsługi tylko raz, a one po prostu działają nawet po wymianie treści.
Oto przykład delegowania zdarzeń bez użycia bibliotek pomocniczych:
(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);
}
})();
Przykład na żywo
Zwróć uwagę, że jeśli klikniesz wiadomości, które są dynamicznie dodawane do strony, kliknięcie zostanie zarejestrowane i obsługiwane, nawet jeśli nie ma kodu, który przechwyciłby zdarzenia na dodawanych nowych akapitach. Zwróć również uwagę, że twoje programy obsługi są tylko wpisami na mapie, a masz jeden moduł obsługujący, document.bodyktóry wykonuje całą wysyłkę. Prawdopodobnie zakorzenisz to w czymś bardziej ukierunkowanym niż document.body, ale masz pomysł. Ponadto w powyższym zasadniczo wysyłamy id, ale możesz dopasować tak złożone lub proste, jak chcesz.
Nowoczesne biblioteki JavaScript, takie jak jQuery , Prototype , YUI , Closure lub dowolne inne, powinny oferować funkcje delegowania zdarzeń, aby wygładzić różnice w przeglądarkach i czysto obsługiwać skrajne przypadki. jQuery z pewnością to robi, zarówno z jego funkcjami, jak livei delegate, które pozwalają określić moduły obsługi przy użyciu pełnego zakresu selektorów CSS3 (a także niektórych).
Na przykład, oto równoważny kod używający jQuery (z wyjątkiem tego, że jestem pewien, że jQuery obsługuje przypadki krawędziowe, które nie są dostępne w surowej wersji powyżej):
(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);
Kopia na żywo