У цьому налаштуванні немає нічого поганого (або він є?), Але чи можу я його трохи згладити?
Подивіться на використання делегування подій замість цього. Саме там ви насправді спостерігаєте за подією в контейнері, який не зникає, а потім використовуєте 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 , Closure або будь-яка інша, повинні пропонувати функції делегування подій, щоб згладити відмінності браузера та чітко обробляти крайні випадки. 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);
Жива копія