Czy wszystkie zdarzenia jquery powinny być powiązane z $(document)?

Skąd się to bierze

Kiedy po raz pierwszy nauczyłem się jQuery, Zwykle załączałem takie zdarzenia:

$('.my-widget a').click(function() {
    $(this).toggleClass('active');
});

Po zapoznaniu się z szybkością selektora i delegacją zdarzeń, przeczytałem w kilku miejscach, że " delegacja zdarzeń jQuery sprawi, że Twój kod będzie szybszy."Więc zacząłem pisać kod w ten sposób:

$('.my-widget').on('click','a',function() {
    $(this).toggleClass('active');
});

Był to również zalecany sposób powielania zachowania przestarzałych .wydarzenie live (). Co jest dla mnie ważne, ponieważ wiele moich stron dynamicznie dodaje/usuwa widgety cały czas. Powyższe nie zachowuje się dokładnie tak .live (), ponieważ tylko elementy dodane do już istniejącego kontenera '.my-widget' uzyskają zachowanie. Jeśli dynamicznie dodam kolejny blok html po uruchomieniu tego kodu, elementy te nie będą miały przypisanych do nich zdarzeń. Tak:

setTimeout(function() {
    $('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);


Co chcę osiągnąć:

  1. stare zachowanie .live () / / Znaczenie przypisywania zdarzeń do nieistniejących jeszcze elementów
  2. korzyści z .on ()
  3. najszybsza wydajność do wiązania zdarzeń
  4. prosty sposób zarządzania zdarzeniami

Dołączam teraz wszystkie zdarzenia takie jak:

$(document).on('click.my-widget-namespace', '.my-widget a', function() {
    $(this).toggleClass('active');
});
Który wydaje się spełniać wszystkie moje cele. (Tak jest wolniej w IE z jakiegoś powodu, nie wiadomo dlaczego?) Jest to szybkie, ponieważ tylko pojedyncze zdarzenie jest powiązane z pojedynczym elementem, a selektor pomocniczy jest oceniany tylko wtedy, gdy zdarzenie wystąpi (Proszę mnie poprawić, jeśli jest to złe tutaj). Przestrzeń nazw jest niesamowita, ponieważ ułatwia przełączanie słuchacz zdarzeń.

Moje Rozwiązanie / Pytanie

Więc zaczynam myśleć, że zdarzenia jQuery powinny być zawsze powiązane z $(document).
Czy Jest jakiś powód, dla którego nie chciałbyś tego zrobić?
Czy można to uznać za najlepszą praktykę? Jeśli nie, to dlaczego?

Jeśli przeczytałeś to wszystko, dziękuję. Doceniam wszelkie opinie/spostrzeżenia.

Założenia:

  1. Using jQuery that support .on() / / conajmniej version 1.7
  2. chcesz, aby zdarzenie zostało dodane do dynamicznie dodawanej treści

Odczyty / Przykłady:

  1. http://24ways.org/2011/your-jquery-now-with-less-suck
  2. http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery
  3. http://www.jasonbuckboyer.com/playground/speed/speed.html
  4. http://api.jquery.com/on/
Author: Maistrenko Vitalii, 2012-10-10

2 answers

No-nie należy wiązać wszystkich przekazanych procedur obsługi zdarzeń z obiektem document. To prawdopodobnie najgorszy scenariusz, jaki możesz stworzyć.

Po pierwsze, delegowanie zdarzeń nie zawsze przyspiesza twój kod. W niektórych przypadkach jest to korzystne, a w niektórych Nie. Delegacja zdarzeń powinna być używana wtedy, gdy faktycznie jej potrzebujesz i kiedy z niej korzystasz. W przeciwnym razie należy powiązać procedury obsługi zdarzeń bezpośrednio z obiektami, w których zdarzenie ma miejsce, tak jak to zrobi ogólnie bądź bardziej wydajny.

Po drugie, nie należy wiązać wszystkich zdarzeń delegowanych na poziomie dokumentu. To właśnie dlatego .live() został przestarzały, ponieważ jest to bardzo nieefektywne, gdy masz wiele wydarzeń związanych w ten sposób. W przypadku delegowanej obsługi zdarzeń znacznie efektywniej jest powiązać je z najbliższym rodzicem, który nie jest dynamiczny.

Po trzecie, nie wszystkie zdarzenia działają lub wszystkie problemy można rozwiązać delegacją. Na przykład, jeśli chcesz przechwycić kluczowe zdarzenia na sterowanie wejściowe i blokowanie nieprawidłowych klawiszy przed wprowadzaniem do kontrolki wejściowej, nie można tego zrobić przy delegowanej obsłudze zdarzeń, ponieważ do czasu pęcherzyków zdarzeń aż do delegowanej obsługi, zostało ono już przetworzone przez kontrolkę wejściową i jest za późno, aby wpływać na to zachowanie.

Oto czasy, w których delegacja zdarzeń jest wymagana lub korzystna:

  • gdy obiekty, na których rejestrowane są zdarzenia, są dynamicznie tworzone/usuwane i nadal chcesz je przechwycić zdarzenia na nich bez konieczności jawnego ponownegoindowania procedur obsługi zdarzeń za każdym razem, gdy tworzysz nowe.
  • gdy masz wiele obiektów, które chcą dokładnie tego samego obsługi zdarzeń (gdzie wiele jest co najmniej setkami). W takim przypadku bardziej wydajne może być Wiązanie jednej delegowanej obsługi zdarzeń zamiast setek lub więcej bezpośrednich procedur obsługi zdarzeń. Uwaga: delegowana obsługa zdarzeń jest zawsze mniej wydajna w czasie wykonywania niż bezpośrednia obsługa zdarzeń.
  • kiedy próbujesz przechwytywanie (na wyższym poziomie w dokumencie) zdarzeń, które występują w dowolnym elemencie dokumentu.
  • gdy projekt wyraźnie używa event bubbling i stopPropagation () do rozwiązania jakiegoś problemu lub funkcji na twojej stronie.

Aby zrozumieć to nieco bardziej, trzeba zrozumieć, jak działają procedury obsługi zdarzeń delegowanych przez jQuery. Kiedy dzwonisz coś takiego:

$("#myParent").on('click', 'button.actionButton', myFn);

Instaluje ogólny program obsługi zdarzeń jQuery na obiekcie #myParent. Po kliknięciu zdarzenia pęcherzyki do tej delegowanej procedury obsługi zdarzeń, jQuery musi przejść przez Listę delegowanych procedur obsługi zdarzeń dołączonych do tego obiektu i sprawdzić, czy Element inicjujący dla zdarzenia pasuje do któregokolwiek z selektorów w delegowanych procedurach obsługi zdarzeń.

Ponieważ selektory mogą być dość zaangażowane, oznacza to, że jQuery musi przeanalizować każdy selektor, a następnie porównać go z charakterystyką oryginalnego celu zdarzenia, aby sprawdzić, czy pasuje do każdego selektora. To nie jest tania operacja. To nic wielkiego, jeśli jest tylko jeden z nich, ale jeśli umieścisz wszystkie selektory w obiekcie document i są setki selektorów do porównania z każdym pojedynczym pęcherzykowym zdarzeniem, może to poważnie pogorszyć wydajność obsługi zdarzeń.

Z tego powodu chcesz skonfigurować delegowane procedury obsługi zdarzeń tak, aby delegowana procedura obsługi zdarzeń była tak blisko obiektu docelowego, jak jest to praktyczne. Oznacza to, że mniej zdarzeń będzie bąbelkować przez każdą delegowaną obsługę zdarzeń, poprawiając tym samym wydajność. Umieszczenie wszystkich delegowanych zdarzeń w obiekcie dokumentu jest najgorszą możliwą wydajnością, ponieważ wszystkie zdarzenia bąbelkowe muszą przejść przez wszystkie delegowane procedury obsługi zdarzeń i zostać ocenione z wszystkimi możliwymi delegowanymi selektorami zdarzeń. Właśnie dlatego {[2] } jest przestarzały, ponieważ to właśnie zrobił .live() i okazał się bardzo nieefektywny.


Tak więc, aby osiągnąć zoptymalizowaną wydajność:

  1. używaj delegowanej obsługi zdarzeń tylko wtedy, gdy faktycznie zapewnia funkcję, której potrzebujesz lub zwiększa wydajność. Nie używaj go zawsze, ponieważ jest łatwy, ponieważ w rzeczywistości go nie potrzebujesz. W rzeczywistości działa gorzej w czasie wysyłania zdarzeń niż bezpośrednie wiązanie zdarzeń.
  2. Załącz delegowane procedury obsługi zdarzeń do najbliższego rodzica do źródła zdarzenia, jak to możliwe. Jeśli używasz delegowanej obsługi zdarzeń, ponieważ masz elementy dynamiczne, dla których chcesz przechwytywać zdarzenia, wybierz najbliższy rodzic, który sam nie jest dynamiczny.
  3. użyj łatwego do oceny selektory delegowanych procedur obsługi zdarzeń. Jeśli zastosowałeś metodę delegowanej obsługi zdarzeń, zrozumiesz, że delegowana obsługa zdarzeń musi być porównywana z wieloma obiektami wiele razy, więc wybranie tak wydajnego selektora, jak to możliwe lub dodanie prostych klas do obiektów, tak aby można było użyć prostszych selektorów, zwiększy wydajność delegowanej obsługi zdarzeń.
 199
Author: jfriend00,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-10 17:28:02

Delegacja zdarzeń jest techniką pisania programów obsługi, zanim element faktycznie istnieje w DOM. Ta metoda ma swoje wady i powinna być stosowana tylko wtedy, gdy masz takie wymagania.

Kiedy należy korzystać z delegowania zdarzeń?

  1. gdy wiąże się wspólny handler dla większej liczby elementów, które wymagają tej samej funkcjonalności. (Np. wiersz tabeli)
    • w przykładzie, jeśli trzeba było powiązać wszystkie wiersze za pomocą Direct bind, to w końcu tworzy się n obsługi dla n wierszy w Ten stół. Używając metody delegowania możesz skończyć z obsługą wszystkich tych w 1 prostym handlerze.
  2. przy częstszym dodawaniu dynamicznej zawartości w DOM (np.: dodawanie / usuwanie wierszy z tabeli)

Dlaczego nie powinieneś używać delegowania zdarzeń?

  1. delegowanie zdarzeń jest wolniejsze w porównaniu z powiązaniem zdarzenia bezpośrednio z elementem.
    • porównuje selektor docelowy na każdym bąbelku, który trafi, porównanie będzie tak drogie, jak jest skomplikowane.
  2. nie ma kontroli nad zdarzeniem, dopóki nie uderzy w element, z którym jest związane.

PS: nawet dla dynamicznej zawartości nie musisz używać metody delegowania zdarzeń, jeśli po wstawieniu zawartości do DOM jesteś związany z obsługą. (Jeśli dynamiczna treść nie jest często usuwana / ponownie dodawana)

 8
Author: Selvakumar Arumugam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-10 17:32:20