В этом нет ничего плохого (или есть?), Но можно ли его немного сгладить?
Взгляните на использование делегирования событий.Вот где вы фактически наблюдаете событие в контейнере, который не исчезает, а затем используете event.target
(или event.srcElement
в IE), чтобы выяснить, где событие действительно произошло, и правильно его обработать..
Таким образом, вы присоединяете обработчики только один раз, и они просто продолжают работать, даже когда вы меняете содержимое.
Вот пример делегирования события без использования вспомогательных библиотек:
(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);
}
})();
Живой пример
Обратите внимание, что если вы нажимаете на сообщения, которые динамически добавляются на страницу, ваш щелчок регистрируется и обрабатывается, даже если нет кода дляперехватывать события на добавляемых новых абзацах.Также обратите внимание, что ваши обработчики являются просто записями на карте, и у вас есть один обработчик на document.body
, который выполняет всю диспетчеризацию.Теперь вы, вероятно, внедрите это в нечто более целенаправленное, чем document.body
, но вы поняли идею.Кроме того, в вышеприведенном случае мы в основном отправляем по id
, но вы можете сделать сопоставление настолько сложным или простым, насколько захотите.
Современные библиотеки JavaScript, такие как jQuery , Prototype, YUI , Закрытие или любой из нескольких других должны предлагать функции делегирования событий для сглаживания различий в браузере и аккуратной обработки краевых случаев.jQuery, безусловно, поддерживает обе функции: live
и delegate
, которые позволяют указывать обработчики с использованием полного набора селекторов CSS3 (а затем и некоторых).
Например, вот эквивалентный код, использующий jQuery (за исключением того, что я уверен, что jQuery обрабатывает крайние случаи, а необработанная версия raw не использует):
(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 copy