window.onload vs document.onload

709

Który jest szerzej obsługiwany: window.onloadlub document.onload?

Chris Ballance
źródło
2
Dokumenty MDN wyjaśnia te windowzdarzenia: onloadi DOMContentLoaded. Przykład użycia :, window.addEventListener('DOMContentLoaded', callback). Od połowy 2019 r. Kompatybilny ze wszystkimi głównymi przeglądarkami. ----- developer.mozilla.org/en-US/docs/Web/API/Window/… ------ developer.mozilla.org/en-US/docs/Web/API/Window/load_event
Craig Hicks
Dla mnie nawet jeszcze, w Firefoksie 75,0 dzisiaj, window.onloadi document.onloadodmienne od siebie! window.onloadwydaje się mieć miejsce później i ma trochę więcej załadowania niż document.onload! (Niektóre rzeczy działają z oknem, które nie działa z dokumentem! Dotyczy to także dokumentu.
Andrew

Odpowiedzi:

722

Kiedy strzelają?

window.onload

  • Domyślnie jest uruchamiany, gdy ładuje się cała strona, w tym jej zawartość (obrazy, CSS, skrypty itp.).

W niektórych przeglądarkach przejmuje teraz rolę document.onloadi uruchamia się, gdy DOM jest również gotowy.

document.onload

  • Jest wywoływany, gdy DOM jest gotowy, co może poprzedzać obrazy i ładowanie innej zawartości zewnętrznej.

Jak dobrze są obsługiwane?

window.onloadwydaje się być najczęściej wspierany. W rzeczywistości niektóre z najnowocześniejszych przeglądarek zostały w pewnym sensie zastąpione document.onloadprzez window.onload.

Problemy z obsługą przeglądarki są najprawdopodobniej powodem, dla którego wiele osób zaczyna korzystać z bibliotek takich jak jQuery do obsługi sprawdzania, czy dokument jest gotowy:

$(document).ready(function() { /* code here */ });
$(function() { /* code here */ });

Dla celów historii. window.onloadvs body.onload:

Podobne pytanie zostało zadane na temat kodowania forów już dawno temu, dotyczące użycia window.onloadover body.onload. Wydawało się, że powinieneś użyć, window.onloadponieważ dobrze jest oddzielić swoją strukturę od akcji.

Josh Mein
źródło
25
Właściwie to stwierdzenie wydaje się być skierowany na wybór pomiędzy window.onloadi <body onload="">która jest zupełnie inna (i „oddzielna struktura z akcji” sprawia, że o wiele więcej sensu w tym kontekście). Nie chodzi o to, że odpowiedź jest zła, ale jej podstawą jest.
Thor84no
2
Ten cytat jest gramatycznie okropny ... czy niektóre (zaznaczone) edytowanie nie powinno pomóc?
Kheldar
@ Thor84no Wreszcie znalazłem czas, aby spojrzeć na to jeszcze raz. Wprowadziłem kilka ulepszeń.
Josh Mein,
@Kheldar Postanowiłem sparafrazować cytat, ponieważ był on dość szorstki.
Josh Mein,
@JoshMein Czy to znaczy, że document.onloadJS jest równoważne z jQuery document.ready?
john cj
276

Ogólna idea jest, że pożary window.onload gdy okno Dokument jest gotowy do prezentacji i document.onload pożarów , gdy drzewa DOM (zbudowany z kodu znaczników w dokumencie) jest zakończona .

Idealnie, subskrybowanie zdarzeń drzewa DOM , pozwala na manipulowanie poza ekranem za pomocą Javascript, nie powodując prawie żadnego obciążenia procesora . Przeciwnie, uruchomieniewindow.onload może zająć trochę czasu , gdy wiele zewnętrznych zasobów musi być jeszcze wymaganych, przeanalizowanych i załadowanych.

► Scenariusz testowy:

Aby zaobserwować różnicę i sposób, w jaki wybrana przeglądarka implementuje wyżej wymienione procedury obsługi zdarzeń , wystarczy wstawić następujący kod w <body>znaczniku - - dokumentu .

<script language="javascript">
window.tdiff = []; fred = function(a,b){return a-b;};
window.document.onload = function(e){ 
    console.log("document.onload", e, Date.now() ,window.tdiff,  
    (window.tdiff[0] = Date.now()) && window.tdiff.reduce(fred) ); 
}
window.onload = function(e){ 
    console.log("window.onload", e, Date.now() ,window.tdiff, 
    (window.tdiff[1] = Date.now()) && window.tdiff.reduce(fred) ); 
}
</script>

► Wynik:

Oto wynikowe zachowanie, które można zaobserwować w przeglądarce Chrome v20 (i prawdopodobnie w większości obecnych przeglądarek).

  • Brak document.onloadzdarzenia
  • onloadodpala dwa razy, gdy zostanie zadeklarowany w środku <body>, raz, gdy zostanie zadeklarowany w środku <head>(gdzie zdarzenie działa jak document.onload).
  • liczenie i działanie zależne od stanu licznika pozwala naśladować oba zachowania zdarzeń.
  • Ewentualnie zadeklaruj window.onloadmoduł obsługi zdarzeń w ramach <head>elementu HTML .

►Przykładowy projekt:

Powyższy kod pochodzi z bazy kodu tego projektu ( index.htmli keyboarder.js).


Aby uzyskać listę procedur obsługi zdarzeń obiektu okna , zapoznaj się z dokumentacją MDN.

Lorenz Lo Sauer
źródło
142

Dodaj detektor zdarzeń

<script type="text/javascript">
  document.addEventListener("DOMContentLoaded", function(event) {
      // - Code to execute when all DOM content is loaded. 
      // - including fonts, images, etc.
  });
</script>


Update March 2017

1 Waniliowy JavaScript

window.addEventListener('load', function() {
    console.log('All assets are loaded')
})


2 jQuery

$(window).on('load', function() {
    console.log('All assets are loaded')
})


Powodzenia.

Akash
źródło
14
„Zdarzenie DOMContentLoaded jest uruchamiane, gdy początkowy dokument HTML zostanie całkowicie załadowany i przeanalizowany, bez oczekiwania na zakończenie ładowania arkuszy stylów, obrazów i podramek”. - developer.mozilla.org/en/docs/Web/Events/DOMContentLoaded Wygląda na to, że nie masz racji co do ładowania wszystkiego podczas tego wydarzenia.
ProfK
2
@ProfK, dziękuję za opinię. Można spróbować window.addEventListener('load', function() {...}). Zaktualizowałem również moją odpowiedź.
Akash
4
W tej odpowiedzi podoba mi się to, że daje proste rozwiązanie w języku javascript. Można by pomyśleć, że większość ludzi uważa, że ​​jQuery jest wbudowane we wszystkie przeglądarki, biorąc pod uwagę, jak często jest on podawany jako jedyna odpowiedź.
Dave Land
Podwójny problem, gdy cholerna jquery trwa zbyt długo, a ładowanie się nie kończy. Uważam, że rozwiązania typu $ (okno) .ready NIGDY nie należy ufać, aby działały.
Shayne,
1
Próbowałem obu w dzisiejszym chrome. Nie czeka na css i czcionki.
movAX13h,
78

Według dokumentów Parsing HTML - Koniec ,

  1. Przeglądarka analizuje źródło HTML i uruchamia odroczone skrypty.

  2. A DOMContentLoadedjest wysyłane w momencie, documentgdy cały HTML został przeanalizowany i uruchomiony. Wydarzenie przechodzi do window.

  3. Przeglądarka ładuje zasoby (takie jak obrazy), które opóźniają ładowanie zdarzenia.

  4. loadZdarzenie jest wywoływane u window.

Dlatego kolejność wykonywania będzie

  1. DOMContentLoadeddetektory zdarzeń windoww fazie przechwytywania
  2. DOMContentLoaded słuchacze wydarzeń z document
  3. DOMContentLoadednasłuchiwanie zdarzeń windoww fazie bubble
  4. loaddetektory zdarzeń (w tym onloadmoduł obsługi zdarzeń) zwindow

Nie należy nigdy wywoływać loaddetektora zdarzeń bąbelkowych (w tym onloadmodułu obsługi zdarzeń) document. loadWywoływane mogą być tylko detektory przechwytywania , ale z powodu obciążenia zasobu podrzędnego, takiego jak arkusz stylów, nie z powodu obciążenia samego dokumentu.

window.addEventListener('DOMContentLoaded', function() {
  console.log('window - DOMContentLoaded - capture'); // 1st
}, true);
document.addEventListener('DOMContentLoaded', function() {
  console.log('document - DOMContentLoaded - capture'); // 2nd
}, true);
document.addEventListener('DOMContentLoaded', function() {
  console.log('document - DOMContentLoaded - bubble'); // 2nd
});
window.addEventListener('DOMContentLoaded', function() {
  console.log('window - DOMContentLoaded - bubble'); // 3rd
});

window.addEventListener('load', function() {
  console.log('window - load - capture'); // 4th
}, true);
document.addEventListener('load', function(e) {
  /* Filter out load events not related to the document */
  if(['style','script'].indexOf(e.target.tagName.toLowerCase()) < 0)
    console.log('document - load - capture'); // DOES NOT HAPPEN
}, true);
document.addEventListener('load', function() {
  console.log('document - load - bubble'); // DOES NOT HAPPEN
});
window.addEventListener('load', function() {
  console.log('window - load - bubble'); // 4th
});

window.onload = function() {
  console.log('window - onload'); // 4th
};
document.onload = function() {
  console.log('document - onload'); // DOES NOT HAPPEN
};

Oriol
źródło
Uruchomiłem twój fragment i document - load - capturerzeczywiście tak się dzieje, co jest sprzeczne z tym, czego oczekiwałem podczas wyszukiwania, dlaczego ładowanie dokumentów nie ma miejsca dla mnie. Dziwnie, jest to niespójne. Czasami się pojawia, czasem nie, czasem pojawia się dwa razy - ale nigdy się nie document - load - bubblezdarza. Sugerowałbym nie używać document load.
błąd
@erroric Dobry punkt. Nie uważałem, że loadzdarzenie jest wysyłane na zasoby zewnętrzne. To zdarzenie nie powoduje bąbelkowania, więc zwykle nie jest wykrywane w dokumencie, ale powinno być w fazie przechwytywania. Te wpisy odnoszą się do obciążenia elementów <style>i <script>. Myślę, że Edge nadaje się do ich wyświetlania, a Firefox i Chrome się mylą.
Oriol
Dzięki Oriol, useCaptureopcja nauczyła mnie czegoś nowego.
Paul Watson
Dziękujemy za podsumowanie analizy i przepływu renderowania z w3. Zastanawiam się po kroku 4 po uruchomieniu zdarzenia „load”, co jeszcze może się stać? Zauważyłem w mojej przeglądarce, że czasami niektóre obiekty są pobierane po uruchomieniu zdarzenia ładowania, chociaż w ogóle nie dotknąłem ani nie wchodziłem w interakcję ze stroną. Czy wiesz, jak nazywają się te obiekty? „Nieblokujące obiekty renderujące?
weefwefwqg3
12

W Chrome window.onload różni się od <body onload="">, podczas gdy są one takie same zarówno w przeglądarce Firefox (wersja 35.0), jak i IE (wersja 11).

Możesz to zbadać za pomocą następującego fragmentu:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <!--import css here-->
        <!--import js scripts here-->

        <script language="javascript">

            function bodyOnloadHandler() {
                console.log("body onload");
            }

            window.onload = function(e) {
                console.log("window loaded");
            };
        </script>
    </head>

    <body onload="bodyOnloadHandler()">

        Page contents go here.

    </body>
</html>

W konsoli Chrome zobaczysz zarówno „okno załadowane” (które pojawia się na początku), jak i „body onload”. Jednak w Firefoksie i IE zobaczysz tylko „obciążenie ciała”. Jeśli uruchomisz „ window.onload.toString()” w konsolach IE i FF, zobaczysz:

„function onload (event) {bodyOnloadHandler ()}”

co oznacza, że ​​przypisanie „window.onload = function (e) ...” zostało zastąpione.

VincentZHANG
źródło
6

window.onloadi onunloadsą skrótami do document.body.onloadidocument.body.onunload

document.onloadi onloadprocedura obsługi wszystkich znaczników HTML wydaje się być zarezerwowana, ale nigdy nie została uruchomiona

' onload' w dokumencie -> prawda

garaboncias
źródło
5

window.onload jednak często są takie same. Podobnie body.onload zmienia się w window.onload w IE.

AnthonyWJones
źródło
1

Window.onload jest jednak standardem - przeglądarka internetowa w PS3 (oparta na Netfront) nie obsługuje obiektu okna, więc nie można go tam używać.

gotofritz
źródło
0

W skrócie

  • windows.onloadnie jest obsługiwany przez IE 6-8
  • document.onload nie jest obsługiwany przez żadną nowoczesną przeglądarkę (wydarzenie nigdy nie jest uruchamiane)

Kamil Kiełczewski
źródło