Jak wywołać funkcję po .append
całkowitym wykonaniu jQuery ?
Oto przykład:
$("#root").append(child, function(){
// Action after append is completly done
});
Problem: Kiedy dołączana jest złożona struktura DOM, obliczenie nowego rozmiaru elementu głównego w wywołaniu zwrotnym funkcji append jest nieprawidłowe. Założenia są takie, że DOM nadal nie jest w pełni załadowany, tylko pierwsze dziecko dodanego złożonego DOM jest.
append()
zajmuje bardzo mało czasu.Odpowiedzi:
Masz tutaj wiele ważnych odpowiedzi, ale żadna z nich tak naprawdę nie mówi ci, dlaczego to działa tak, jak działa.
W JavaScript polecenia są wykonywane pojedynczo, synchronicznie w kolejności, w jakiej przychodzą, chyba że wyraźnie powiesz im, aby były asynchroniczne, używając limitu czasu lub interwału.
Oznacza to, że Twoja
.append
metoda zostanie wykonana i nic więcej (pomijając potencjalne przekroczenia czasu lub interwały, które mogą istnieć) nie będzie wykonywane, dopóki ta metoda nie zakończy swojego zadania.Podsumowując, nie ma potrzeby oddzwaniania, ponieważ
.append
będą uruchamiane synchronicznie.źródło
Chociaż Marcus Ekwall ma całkowitą rację co do synchroniczności dołączania, odkryłem również, że w dziwnych sytuacjach czasami DOM nie jest całkowicie renderowany przez przeglądarkę po uruchomieniu następnej linii kodu.
W tym scenariuszu rozwiązania shadowdiver są zgodne z poprawnymi rozwiązaniami - z użyciem .ready - jednak znacznie łatwiej jest połączyć wywołanie z oryginalnym plikiem.
$('#root') .append(html) .ready(function () { // enter code here });
źródło
Cóż, mam dokładnie ten sam problem z przeliczeniem rozmiaru i po wielu godzinach bólu głowy muszę się nie zgodzić z
.append()
zachowaniem ściśle synchronicznym. Cóż, przynajmniej w Google Chrome. Zobacz poniższy kod.var input = $( '<input />' ); input.append( arbitraryElement ); input.css( 'padding-left' );
Właściwość padding-left jest poprawnie pobierana w przeglądarce Firefox, ale w przeglądarce Chrome jest pusta. Przypuszczam, że podobnie jak wszystkie inne właściwości CSS. Po kilku eksperymentach musiałem zadowolić się opakowaniem „gettera” CSS
setTimeout()
z 10 ms opóźnieniem, które, jak wiem, jest brzydkie jak cholera, ale jedyne działające w Chrome. Byłbym bardzo wdzięczny, gdyby ktoś z Was wpadł na pomysł, jak lepiej rozwiązać ten problem.źródło
.ready()
znacznie lepsze i bardziej eleganckie rozwiązanie.Jestem zaskoczony wszystkimi odpowiedziami tutaj ...
Spróbuj tego:
window.setTimeout(function() { /* your stuff */ }, 0);
Zwróć uwagę na limit czasu 0. To nie jest dowolna liczba ... jak rozumiem (chociaż moje rozumienie może być nieco niepewne), istnieją dwie kolejki zdarzeń javascript - jedna dla zdarzeń makro i jedna dla zdarzeń mikro. „Większa” kolejka o zasięgu zawiera zadania, które aktualizują interfejs użytkownika (i DOM), podczas gdy mikro kolejka wykonuje operacje typu szybkiego zadania.
Pamiętaj również, że ustawienie limitu czasu nie gwarantuje, że kod będzie działał dokładnie przy tej określonej wartości. To zasadniczo powoduje umieszczenie funkcji w wyższej kolejce (tej, która obsługuje UI / DOM) i nie uruchamia jej przed upływem określonego czasu.
Oznacza to, że ustawienie limitu czasu na 0 powoduje umieszczenie go w części UI / DOM kolejki zdarzeń javascript, aby uruchomić ją przy najbliższej możliwej okazji.
Oznacza to, że DOM zostanie zaktualizowany o wszystkie poprzednie elementy kolejki (takie jak wstawione za pośrednictwem
$.append(...);
, a kiedy Twój kod zostanie uruchomiony, DOM jest w pełni dostępny.(ps - nauczyłem się tego z Secrects of the JavaScript Ninja - świetnej książki: https://www.manning.com/books/secrets-of-the-javascript-ninja )
źródło
setTimeout()
od lat, nie wiedząc dlaczego. Dziękuję za wyjaśnienie!Mam inny wariant, który może się komuś przydać:
$('<img src="http://example.com/someresource.jpg">').load(function() { $('#login').submit(); }).appendTo("body");
źródło
...on('load', function(){ ...
uważają , że jest to przestarzałe i usunięte, to prawda, ale nadal możesz z niego korzystać, jak tutaj: stackoverflow.com/a/37751413/2008111Natknąłem się na ten sam problem i znalazłem proste rozwiązanie. Dodaj po wywołaniu funkcji append dokument gotowy.
$("#root").append(child); $(document).ready(function () { // Action after append is completly done });
źródło
Używanie
MutationObserver
może działać jak callback dlaappend
metody jQuery :Wyjaśniłem to w innym pytaniu i tym razem podam tylko przykład dla nowoczesnych przeglądarek:
// Somewhere in your app: var observeDOM = (() => { var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; return function(obj, callback){ if( MutationObserver ){ // define a new observer var obs = new MutationObserver(function(mutations, observer){ if( mutations[0].addedNodes.length || mutations[0].removedNodes.length ) callback(mutations); }); // have the observer observe foo for changes in children obs.observe( obj, { childList:true, subtree:true }); return obs; } } })(); ////////////////// // Your code: // setup the DOM observer (on the appended content's parent) before appending anything observeDOM( document.body, ()=>{ // something was added/removed }).disconnect(); // don't listen to any more changes // append something $('body').append('<p>foo</p>');
źródło
Myślę, że odpowiedź na to pytanie jest dobra, ale jest to trochę bardziej specyficzne dla obsługi „subChild_with_SIZE” (jeśli pochodzi od rodzica, ale możesz go dostosować z miejsca, w którym może być)
$("#root").append( $('<div />',{ 'id': 'child' }) ) .children() .last() .each(function() { $(this).append( $('<div />',{ 'id': $(this).parent().width() }) ); });
źródło
$.when($('#root').append(child)).then(anotherMethod());
źródło
$.when
działa tylko dla tych obiektów, które zwracają obiekt obiecanyanotherMethod()
od razu .. To nie jest przekazywane jako wywołanie zwrotne.funkcja dołączania Jquery zwraca obiekt jQuery, więc możesz po prostu oznaczyć metodę na końcu
$("#root").append(child).anotherJqueryMethod();
źródło
W przypadku obrazów i innych źródeł możesz użyć tego:
$(el).one('load', function(){ // completed }).each(function() { if (this.complete) $(this).load(); });
źródło
Najczystszym sposobem jest robienie tego krok po kroku. Użyj funkcji each, aby przejść przez każdy element. Jak tylko ten element zostanie dołączony, przekaż go do kolejnej funkcji, aby przetworzyć ten element.
function processAppended(el){ //process appended element } var remove = '<a href="#">remove</a>' ; $('li').each(function(){ $(this).append(remove); processAppended(this); });
źródło
Napotkałem ten problem podczas kodowania HTML5 na urządzenia mobilne. Niektóre kombinacje przeglądarki / urządzenia powodowały błędy, ponieważ metoda .append () nie odzwierciedlała natychmiastowo zmian w DOM (powodując awarię JS).
Szybkim i brudnym rozwiązaniem tej sytuacji było:
var appint = setInterval(function(){ if ( $('#foobar').length > 0 ) { //now you can be sure append is ready //$('#foobar').remove(); if elem is just for checking //clearInterval(appint) } }, 100); $(body).append('<div>...</div><div id="foobar"></div>');
źródło
Tak, możesz dodać funkcję zwrotną do dowolnego wstawienia DOM:
$myDiv.append( function(index_myDiv, HTML_myDiv){ //.... return child })
Sprawdź dokumentację JQuery: http://api.jquery.com/append/
A oto praktyczny, podobny przykład: http://www.w3schools.com/jquery/ tryit.asp? filename = tryjquery_html_prepend_func
źródło
.prepend()
metodę przez: $ ("p"). Prepend (function (n, pHTML) {return "<b> Ten element p </b> (\" <i > "+ pHTML +" </i> \ ") <b> ma indeks" + n + "</b>.";Niedawno napotkałem podobny problem. Rozwiązaniem dla mnie było odtworzenie kolekcji. Spróbuję pokazać:
var $element = $(selector); $element.append(content); // This Doesn't work, because $element still contains old structure: $element.fooBar(); // This should work: the collection is re-created with the new content: $(selector).fooBar();
Mam nadzieję że to pomoże!
źródło
W jquery możesz użyć zaraz po dodaniu pliku
$(function(){ //code that needs to be executed when DOM is ready, after manipulation });
$ () wywołuje funkcję, która albo rejestruje wywołanie zwrotne gotowego do DOMU (jeśli przekazano do niego funkcję), albo zwraca elementy z DOM (jeśli przekazano do niego selektor lub element)
Możesz znaleźć więcej
różnic między $ a $ () w jQuery
http://api.jquery.com/ready/
źródło
Wiem, że to nie jest najlepsze rozwiązanie, ale najlepsza praktyka:
$("#root").append(child); setTimeout(function(){ // Action after append },100);
źródło
$('#root').append(child); // do your work here
Append nie ma wywołań zwrotnych, a jest to kod, który jest wykonywany synchronicznie - nie ma ryzyka, że NIE zostanie wykonany
źródło
$('#root').append(child).anotherMethod();
źródło