Click nie działa po załadowaniu ajaxem – jQuery

Jeśli wykorzystuje AJAX na swojej stronie miej na uwadze, że zdarzenia jak click, submit, hover mogą nie działać jeśli nie dołączysz ich poprawnie. Będę opierać się na zdarzeniu click, aby opisać problem, ale dotyczy on większości zdarzeń w jQuery.

Przykładowe dane

Powiedzmy, że mam jakąś listę, która jest podzielona na kategorie. Możesz wybrać, która kategoria jest widoczne a wpisy załadują się poprzez ajax. Każdy wpis ma ukryty opis, który pokazuje się po kliku. O tak:

$('.toggle-item').click(function(e){
    e.preventDefault();
    $(this).parent().next('.category-item-content').toggle();
});

Kiedy załaduję stronę wszystko działa dobrze dopóki nie zmienię kategorii. Ajax nadal działa prawidłowo, ale pokaż/ukryj opis we wpisach już nie. WAT?

przykład online – Przykładowe dane

Rozwiązanie 1

Zdarzenie click jest przypisywane do istniejących elementów podczas ładowania strony. Słowo klucz to “istniejące”. Kiedy ładujemy coś poprzez ajax manipulujemy DOM. Wstawiamy zupełnie nowy element. Tak więc musimy przypisać to zdarzenie już po wstawieniu nowej treści. Jeśli używasz funkcji .load() (jak w moim przykładzie) wystarczy, że umieścisz $(‘.toggle-item’).click() w funkcji callback:

$('#category-wrapper').load(link.attr('href'),function(responseText, textStatus, XMLHttpRequest){
	$('#category-nav a').removeClass('active');
	link.addClass('active');
	/* Toggle category item */
	$('.toggle-item').click(function(e){
		e.preventDefault();
		$(this).parent().next('.category-item-content').toggle();
	});
});

w ten sposób przypisujemy zdarzenie click do nowododanych elementów.

Oczywiście moglibyśmy przenieść $(‘.toggle-item’).click() do zewnętrznej funkcji, żeby się nie powtrarzać (dla lepszego zarządzania itd, wiadomo, DRY?).

Jeśli korzystasz z funkcji .ajax() zamiast .load() po prostu przypisz zdarzene w części .done().

Rozwiązanie 1 – sprawdź

Rozwiązanie 2

Co jeśli nie chcemy przypisywać zdarzenia za każdym razem gdy wywołujemy ajax. Czy nie ma czasem bardziej “globalnego” rozwiązania? Oczywiście, że jest. Możemy użyć funkcji .on(). Hurra!

Ale czekaj!

Czy czasem .click() to nie jest to samo co .on(‘click’)? To jest to samo. Ale patrz – możemy delegować zdarzenia.

Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time 

Tak więc zamiast przypisywać zdarzenie po wykonanym zapytaniu ajax, przypisujemy go bardziej “globalnie”:

/* Toggle category item */
$('#category-wrapper').on('click','.toggle-item',function(e){
	e.preventDefault();
	$(this).parent().next('.category-item-content').toggle();
});

Moglibyśmy przypisać je do$(‘body’).on(‘click’,’.toggle-item’,function(){}); ale:

For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.

Rozwiązanie 2 – sprawdź

Pamiętaj – zdarzenie delegowane musy być przypisane do elementu, który istnieje na stronie w momencie wykonywania kodu i który nie jest modifykowany podczas zapytań ajaxowych – swego rodzaju kontener. To jest powód dla, którego ludzie przypisują zdarzenie do body. Jednak jeśli jest to możliwe wybierz element, który jest bliżej docelowego elementu.

Tak przy okazji, we wcześniejszych wersjach jQuery używaliśmy funkcji .line() lub .delegate() w miejsu .on().

0 0 vote
Article Rating