Как стать автором
Обновить

Комментарии 36

по-моему, лучше вешать событие тогда уже на document, а не на document.body
подход интересный.. хотя и сомнительный
Интересно, а чем подкреплён агрумент "Чем меньше приемников событий прикреплено к документу, тем лучше. Они все загружаются в память и в чрезвычайных случаях могут сильно замедлить работу браузеров." ? И как определить то количество приемников, которое действительно будет тормозить броузер ? (один приемник не тормозит, два не тормозит... А сто приемников ? А десять тысяч приемников ?)

Допустим, что тысяча приемников событий действительно тормозят броузер и возьмём какую-нибудь страницу с функциональностью gmail.com. Тогда последний приведённый код внесёт в код как минимум неразбериху и нечитаемость кода =(

Плюс к тому: представьте себе в функции MMNav.init тысячу разных алгоритмов обработки событий в одном месте. Конструкции типа "если объект такой-то, то делаем это иначе если..." не только не ускорят обработку событий, но и начисто подвесят любой броузер.
И как определить то количество приемников, которое действительно будет тормозить броузер ?

опытным путем, имхо

тысячу разных алгоритмов обработки событий в одном месте

предложенное решение не претендует на универсальность. Если у вас обрабатываются событий типа onmouseover, onmouseout, то лучше пользоваться самым первым из предложенных примеров, ибо отслеживать на родительском контейнере все движения мыши нам совсем ни к чему
Опытным путём, конечно всё можно сделать =) Но ведь аргумент про уменьшение приемников является основой всех размышлений. И только в случае когда эффект от уменьшения намного превысит недостатки метода, его стоит повсеместно использовать.

Кстати, а зачем оптимизировать onclick ? Ведь человек мышкой кликает с гораздо меньшей скоростью, чем работает программа =)
Вот тест, который сравнивает производительность двух методов.
Event Delegation versus Event Handling.
Думаю, комментарии излишни.
Во-первых, события лучше назначать addEventListener || attachEvent.
Во-вторых, предложенные "альтернативные" методы крайне негибкие, они подразумевают одинаковый формат всех ссылок внутри элемента.
И, в-третьих, 60 мс для обработки нужных ссылок — чертовски (!) малое время, чтобы его уменьшать.

В последнее время я наблюдаю лёгкое помешательство на "ускорении js".
А в данном случае, "сэкономив" лишние несколько мс, вы ещё и потерятете возможность переопределять уникальные ссылки. Оно вам надо?
у вас есть данные по скорости работы addEventListener || attachEvent? помнится мне, что все DOM-методы в IE работают несколько медленно
AMD3000+, 10000 а-элементов (~7 страниц одних сплошных коротких ссылок) — onclick:110 ms, attachEvent:170 ms.
Разница в 60 ms не так страшна, как перезаписанное кем-то событие.
Ниже приведены мои данные. IE особенно плохо с этим работает. К тому же, перезапись можно и устранить, добавив простое условие.

Для разработки очень больших проектов, перезапись, наверное, будет актуальна, но для 90–95% разработок это совершенно несущественно, потому что за конкретную реализацию JS-функционала обычно отвечают один–два человека, а они уже могут договориться между собой (хотя в случае даже одного человека это может быть нетривиальной задачей :)
Количество телодвижений для реализации каждого метода, да и проведенный мной тест показывают, что вам ничто не мешает писать безопасный код. Даже если весь ваш js это пара функций в хидере.
Не знаю, откуда взято 90-95%, но, даже в этом случае, «небольшие проекты» вполне могут подрасти со временем. И к чему вам тогда, спрашивается, этот потенциальный геммор?
еще есть Greasemonkey и им подобные, кто захочет прогуляться по вашему приложению и понадобавлять событий)
там, в заключении, исправь пожалуйста
«старых версиях _браузерах_» (на «браузеров»)
спасибо :)
А если на странице много компонентов, каждый из которых содержит собственные ссылки/кнопки или другие элементы, для которых нужно обрабатывать события? Если каждый будет развешивать свои обработчики на document.body — помойка получится.
Имхо каждый сверчок должен знать свой шесток — то бишь выше своего контейнера не подниматься.
К тому же, даже при использовании этого общего способа, логично было бы использовать 'attachEvent' (опять же со всеми требуемыми финтами для разных браузеров), а не буквальное определение одного обработчика. Не надо жадничать — другим скриптам тоже может оказаться потребен 'window.load'.

Дальше. Функция function getEventTarget(e) в данной интерпретации явно предназначена исключительно для обработки событий, происходящих над ссылками. Причём ссылками, у которых установлен атрибут "href". Я бы предложил либо переименовать её, либо сделать методом 'MMNav', чтобы избежать конфликта имён. Да и просто инкапсулировать частную функциональность в конкретном классе.
насчет производительности, небольшая модификация описанного в статье кода (последний пример) 10000 раз подключала этот обработчик. Вот результаты (AddEvent / onclick):

IE 5.5 = 800/203
IE 6 = 830/280
IE 7 = 860/270
Firefox 2 = 310/203
Opera 9 = 125/63
Safari 3 = 31 (!)/31 (!)
Вот мой тест:
window.onload = function() // .onload исключительно для эксперимента ;)
{
//
function $time(){ return (new Date()).getTime(); }

//
var amount = 10000, i;
var anch = '';
for(i = 0; i link x';
document.body.innerHTML = anch;

//
var solver = function(){ alert('click') };
var els = document.body.getElementsByTagName('a');
//alert(els.length);

//
var time = $time();
for(i=0; i
Сорри, вот тест: http://disaen.com/temp/event_test/
Результаты.
FF: onclick — 480 / addEventListener — 860;
Opera: onclick — 500 / addEventListener — 550;
IE (а вот тут я ранее вас обманул, всё, оказывается, интереснее): attachEvent — 170 / onclick — 110 (проверьте, плиз, у себя).
Ox, конец рабочего дня не вяжется с отсутствием кнопочки "редактировать".
IE: onclick — 170 / attachEvent — 110.
Ещё раз сорри.
там тест недостаточно "чистый", потому что сначала генерит код, потом его вставляет (innerHTML используется наряду с addEvent), т.е. я бы сделал статичный HTML, с которым бы и игрался
Согласен. Измененные тесты лежат по тому же адресу.
Результаты, более аккуратно собранные:
FF: onclick — 450 / addEventListener — 500;
Opera: onclick — 170 / addEventListener — 150(!);
IE: onclick — 370 / attachEvent — 110(!).
Проверьте ещё сами, пожалуйста.
http://exp.lusever.programica.ru/test-ev…
Можете протестировать Вашу версию, немного доработанную. У оперы вообще в среднем:
onclick: 118ms
attachEvent: 81ms
addEventListener: 89ms
Вот тест, который сравнивает производительность двух методов.
Event Delegation versus Event Handling.
Думаю, комментарии излишни.
Статья довольно интересна, но, имхо, есть более хороший способ.


document.onclick = function() {
var f = arguments.callee, e = arguments[0] || window.event, t = e.target || e.srcElement;

if (f.last && t !== f.last) {
f.last = null;
}

if ((t.nodeName == "a") && (t.className == 'bundle')) {
t.href += '?name=value';
f.last = t;
}
}


Код обрабатывается быстро (если кто-то протестирует и выложит результат - буду весьма благодарен), утечек памяти нет. Правда не знаю о совместимости с Safari...
А что делать с onsubmit?
а чем оно отличается от других событий? просто еще одна "перемычка"-мост появится
Вроде onsubmit на document не срабатывает в ie.
да, в IE проблемы в этом плане, точно. Можно привести пример, когда нам нужно эмулировать onsubmit, и это не достигается другими средствами (например, формированием GET-запроса или "скрытой" отправкой формы)?
Мне кажется эмулировать это последнее что обычно нужно. Обычно на onsubmit нужно отреагировать и отменить.
Можно смотреть за всплывающими событиями: keyup','mousedown','activate'.
Если обработчик сработает на элементе form или у которой есть предок form, подключаем к этой form нужный нам обработчик. Конечно надо следить чоб на одну и туже форму не навесить несколько обработчиков.
шибко мудро :)
могу выложить код как я это сделал, один раз сделал, несколько раз правил, и везде использую.. куда выложить только? я щас переосмысливаю свои наработки и выкладывать в свой гуглкод не хочется, чтобы не запутать.
В сущности такая байда нужна только для проверки вводимых в форму полей.. вот я и забацал валидатор, ну он еще кое чо может делать во время проверки
Посмотрите еще одно решение по отслеживанию событий на странице.
Вообще свойство "всплывать" у некоторых событий удобно использовать во многих задачах.
абалдеть html теги не сработали, вообщем ссылка по теме в моем профиле
а можно пояснить, чем это кардинально отличается от проекта Сумина http://jsx.ru/ ? Т.е. идея одна и та же, просто у Вас она проработана меньше, насколько я смог понять
в jsx другая идея, там вся фишка в произвольных событиях на произвольных объектах, а обработку всплывающих обектов я у него не видел, внимательнее чтоли посмотреть.. да он сам на конференции говорил что его движок использует джиквари или бейс2, в этих движках обработчики событий навешиваются на каждый элемент. Если в последнее время ничто не поменялось. У них все шикарно работает до тех пор пока элементы вставлять не начнешь.
После подключения обработчика события на элементы определенной категории вставленные элементы с такой же категорией небудут обработаны, их снова нужно будет подключать.

Насчет проработанности, я еще не дорос до создания супер пупер библиотеки, я только предлагаю компактные решения конкретной проблемы.
jsx я делал для больших, масштабируемых и как целиком, так и по частям reusable (не могу подобрать русский перевод) интерфейсов.

Система событий в jsx никоим образом не влияет на систему событий в DOM она идет паралельно и предназначена для удаления жестких ссылок между объектами и компонентами.
Собственно тут подробно описанно http://jsx.ru/Texts/CustomEvents/index.html.

Как при таком подходе работать с DOM событиями решать разработчику.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории