Staram się zrozumieć tę szczególną różnicę między bezpośrednich i delegowanych obsługi zdarzeń przy użyciu jQuery .on () metody . W szczególności ostatnie zdanie w tym akapicie:
Gdy
selector
podano a, program obsługi zdarzeń jest określany jako delegowany . Procedura obsługi nie jest wywoływana, gdy zdarzenie występuje bezpośrednio w powiązanym elemencie, ale tylko w przypadku elementów podrzędnych (elementów wewnętrznych), które pasują do selektora. jQuery przesuwa zdarzenie z miejsca docelowego zdarzenia do elementu, do którego jest dołączona procedura obsługi (tj. najbardziej wewnętrzna do najbardziej zewnętrznego elementu) i uruchamia procedurę obsługi dla wszystkich elementów wzdłuż tej ścieżki pasujących do selektora.
Co to znaczy „uruchamia procedurę obsługi dla dowolnych elementów”? Zrobiłem stronę testową, aby poeksperymentować z tą koncepcją. Ale obie poniższe konstrukcje prowadzą do tego samego zachowania:
$("div#target span.green").on("click", function() {
alert($(this).attr("class") + " is clicked");
});
lub,
$("div#target").on("click", "span.green", function() {
alert($(this).attr("class") + " is clicked");
});
Może ktoś mógłby odnieść się do innego przykładu, aby wyjaśnić tę kwestię? Dzięki.
Odpowiedzi:
Przypadek 1 (bezpośredni):
== Hej! Chcę, aby każdy span.green wewnątrz celu div # nasłuchiwał: kiedy zostaniesz kliknięty, zrób X.
Przypadek 2 (delegowany):
== Hej, div # target! Kiedy którykolwiek z elementów podrzędnych „span.green” zostanie kliknięty, zrób z nimi X.
Innymi słowy...
W przypadku 1 każdemu z tych przęseł podano indywidualne instrukcje. Jeśli zostaną utworzone nowe zakresy, nie usłyszą instrukcji i nie będą reagować na kliknięcia. Każdy zakres jest bezpośrednio odpowiedzialny za swoje własne zdarzenia.
W przypadku 2 instrukcję przekazano tylko kontenerowi; odpowiada za zauważanie kliknięć w imieniu swoich elementów podrzędnych. Praca nad łapaniem zdarzeń została oddelegowana . Oznacza to również, że instrukcja zostanie wykonana dla elementów potomnych, które zostaną utworzone w przyszłości.
źródło
on()
dopuszcza się dwa argumenty, skoro byłoby to prawie takie samo jak używanieclick()
?e.target
będzie początkowym celem zdarzenia kliknięcia (może być węzłem podrzędnym, jeślispan.green
ma dzieci). Z wnętrza programu obsługi należy użyćthis
odwołania. Zobacz to skrzypce .Pierwszy sposób
$("div#target span.green").on()
wiąże procedurę obsługi kliknięcia bezpośrednio z zakresami, które pasują do selektora w momencie wykonywania kodu. Oznacza to, że jeśli inne rozpiętości zostaną dodane później (lub zmienisz ich klasę, aby pasowały), przegapią one i nie będą miały modułu obsługi kliknięć. Oznacza to również, że jeśli później usuniesz „zieloną” klasę z jednego z zakresów, jego moduł obsługi kliknięć będzie nadal działał - jQuery nie śledzi sposobu przypisania modułu obsługi i sprawdza, czy selektor nadal pasuje.Drugi sposób
$("div#target").on()
,, wiąże moduł obsługi kliknięcia z pasującymi elementami div (znowu, jest to przeciwko tym, które pasują w danym momencie), ale kiedy nastąpi kliknięcie gdzieś w elemencie div, funkcja obsługi zostanie uruchomiona tylko wtedy, gdy kliknięcie wystąpiło nie tylko w elemencie div, ale w elemencie podrzędnym pasującym do selektora w drugim parametrze do.on()
„span.green”. W ten sposób nie ma znaczenia, kiedy te rozpiętości podrzędne zostały utworzone, kliknięcie ich nadal będzie uruchamiać procedurę obsługi.Dlatego w przypadku strony, która nie dodaje ani nie zmienia swojej zawartości dynamicznie, nie zauważysz różnicy między tymi dwiema metodami. Jeśli dynamicznie dodajesz dodatkowe elementy podrzędne, druga składnia oznacza, że nie musisz się martwić o przypisywanie do nich programów obsługi kliknięć, ponieważ już raz to zrobiłeś w nadrzędnym.
źródło
Wyjaśnienie N3dst4 jest doskonałe. Na tej podstawie możemy założyć, że wszystkie elementy potomne znajdują się wewnątrz ciała, dlatego musimy użyć tylko tego:
Działa z wydarzeniem bezpośrednim lub delegowanym.
źródło
$('body').on()
delegacja z.element
powinna zachowywać się dokładnie tak samo jak natywnadocument.body.addEventHandler()
z elementemif (Event.target.className.matches(/\belement\b/))
wywołania zwrotnego. Może być trochę wolniejszy w jQuery z powodu$.proxy
narzutu, ale nie cytuj mnie na ten temat.Styczne do PO, ale koncepcja, która pomogła mi rozwikłać zamieszanie z tą funkcją, polega na tym, że powiązane elementy muszą być rodzicami wybranych elementów .
.on
..on()
.Delegowanie nie działa tak jak .find (), wybierając podzbiór powiązanych elementów. Selektor ma zastosowanie tylko do ścisłych elementów potomnych.
bardzo różni się od
W szczególności, aby uzyskać korzyści ze wskazówek @ N3dst4 w przypadku „elementów, które zostaną utworzone w przyszłości”, element powiązany musi być stałym elementem nadrzędnym . Następnie wybrane dzieci mogą przychodzić i wychodzić.
EDYTOWAĆ
Lista kontrolna, dlaczego delegowanie
.on
nie działaPodstępne powody, dla których
$('.bound').on('event', '.selected', some_function)
może nie działać:.on()
.stopPropagation()
.(Pomijając mniej skomplikowane przyczyny, takie jak błędnie napisany selektor).
źródło
Napisałem post z porównaniem wydarzeń bezpośrednich i delegowanych. Porównuję czysty js, ale ma to samo znaczenie dla jquery, które tylko je hermetyzuje.
Wniosek jest taki, że delegowana obsługa zdarzeń dotyczy dynamicznej struktury DOM, w której powiązane elementy mogą być tworzone podczas interakcji użytkownika ze stroną (nie ma potrzeby ponownego wiązania), a bezpośrednia obsługa zdarzeń dotyczy statycznych elementów DOM, gdy wiemy, że struktura nie ulegnie zmianie.
Więcej informacji i pełne porównanie - http://maciejsikora.com/standard-events-vs-event-delegation/
Używanie zawsze delegowanych procedur obsługi, które, jak widzę, jest obecnie bardzo modne, nie jest właściwe, wielu programistów używa go, ponieważ „powinno być używane”, ale prawda jest taka, że bezpośrednie procedury obsługi zdarzeń są lepsze w niektórych sytuacjach i przy wyborze metody, która powinna być obsługiwana znajomość różnic.
źródło