Читать «Разгони свой сайт» онлайн - страница 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;

}

}

Простота и элегантность данного подхода должны быть очевидны, но у него есть и некоторое количество преимуществ в плане производительности:

Чем меньше приемников событий прикреплено к документу, тем лучше. Они все загружаются в память и в чрезвычайных случаях могут сильно замедлить работу браузеров. Также это увеличивает число замыканий, что чревато утечками памяти. Подробнее рассказывается далее в этой главе.