Читать «Разгони свой сайт» онлайн - страница 99
Николай Мациевский
Существует возможность добавлять обработчики событий в комплект к уже существующим обработчикам. При вызове функции мы передаем ей объект, который нужно привязать к событию, тип события и имя функции.
function addEvent(object, eventType, function){
if (object.addEventListener){
object.addEventListener(eventType, function, false);
return true;
} else {
if (object.attachEvent){
var r = object.attachEvent(\"on\"+eventType, function);
return r;
} else {
return false;
}
}
}
События — довольно сложная тема в Javascript. Для разработки простых веб-сайтов указанных примеров достаточно, но если мы переходим к разработке веб-приложений, тут ситуация многократно усложняется. Поэтому стоит быть внимательным к их функционированию в условиях отключенного или неподдерживаемого JavaScript.
Ускоряем обработку событий
Давайте рассмотрим, как можно использовать методы «ненавязчивого» JavaScript для максимального ускорения обработки событий в браузере. Мы можем уменьшить число приемников событий, которые назначены документу, путем определения одного приемника для контейнера и проверки в обработчике, из какого дочернего элемента всплыло это событие.
Предположим, что у нас основная навигация по сайту включает шесть ссылок сверху, четырем из которых требуются обработчики событий, чтобы поменять у них атрибут href. У этих четырех ссылок атрибут class выставлен в bundle.
Скорее всего, ситуация будет выглядеть следующим образом.
var MenuNavigation = {
init: function() {
var links = navigation.getElementsByTagName('a');
for ( var i = 0, j = links.length; i < j; ++i ) {
if ( /bundle/i.test(links[i].className) ) {
links[i].onclick = this.onclick;
}
}
},
onclick: function() {
this.href = this.href + '?name=value';
return true;
}
}
В этом фрагменте довольно много лишнего. Во-первых, метод getElementsByTagName просматривает каждый дочерний DOM-узел в элементе mainNav, чтобы найти все ссылки. Затем мы еще раз пробегаем по всему найденному массиву, чтобы проверить имя класса каждой ссылки. Это пустая трата процессорного времени на каждом этапе. И это замедление загрузки страницы на уровне JavaScript-логики.
Немного усложним
Можно прикрепить один-единственный обработчик событий к элементу mainNav, чтобы затем отслеживать все клики на ссылки внутри него:
var MenuNavigation = {
init: function() {
navigation.onclick = this.onclick;
},
onclick: function(e) {
if ( /bundle/i.test(e.target.className) ) {
e.target.href = e.target.href + '?name=value';
}
return true;
}
}
Простота и элегантность данного подхода должны быть очевидны, но у него есть и некоторое количество преимуществ в плане производительности:
Чем меньше приемников событий прикреплено к документу, тем лучше. Они все загружаются в память и в чрезвычайных случаях могут сильно замедлить работу браузеров. Также это увеличивает число замыканий, что чревато утечками памяти. Подробнее рассказывается далее в этой главе.