Cykl życia strony HTML ma trzy ważne zdarzenia:
-
DOMContentLoaded
– przeglądarka w pełni załadowana HTML, a drzewo DOM jest zbudowane, ale zasoby zewnętrzne, takie jak obrazy<img>
i arkusze stylów, mogły jeszcze nie zostać załadowane. -
load
– ładowany jest nie tylko HTML, ale także wszystkie zasoby zewnętrzne: obrazy, style itp. -
beforeunload/unload
– użytkownik opuszcza stronę.
Każde zdarzenie może być przydatne:
-
DOMContentLoaded
zdarzenie – DOM jest gotowy , więc program obsługi może wyszukiwać węzły DOM, inicjować interfejs. -
load
zdarzenie – ładowane są zasoby zewnętrzne, więc stosowane są style, znane są rozmiary obrazów itp. -
beforeunload
zdarzenie – użytkownik wychodzi: możemy sprawdzić, czy użytkownik zapisał zmiany i zapytać, czy naprawdę chce wyjść. - – użytkownik prawie wyszedł, ale nadal możemy zainicjować pewne operacje, takie jak wysyłanie statystyk.
Przyjrzyjmy się szczegółom tych wydarzeń.
DOMContentLoaded
Zdarzenie DOMContentLoaded
ma miejsce w obiekcie document
.
Mamy musi użyć addEventListener
, aby to złapać:
Na przykład:
W tym przykładzie moduł obsługi DOMContentLoaded
działa po załadowaniu dokumentu, dzięki czemu może zobaczyć wszystkie elementy, w tym <img>
poniżej.
Ale nie czeka na załadowanie obrazu. Dlatego alert
pokazuje zero rozmiarów.
Na pierwszy rzut oka zdarzenie DOMContentLoaded
jest bardzo proste. Drzewo DOM jest gotowe – oto wydarzenie. Jest jednak kilka osobliwości.
DOMContentLoaded i skrypty
Gdy przeglądarka przetwarza dokument HTML i napotyka tag <script>
, musi zostać wykonana przed kontynuowaniem budowania DOM. To środek ostrożności, ponieważ skrypty mogą chcieć zmodyfikować DOM, a nawet wprowadzić do niego document.write
, więc DOMContentLoaded
musi poczekać.
Więc DOMContentLoaded na pewno dzieje się po takich skryptach:
W powyższym przykładzie najpierw widzimy „Biblioteka załadowana…”, a następnie „DOM gotowy!” (wykonywane są wszystkie skrypty).
Istnieją dwa wyjątki od tej reguły:
- Skrypty z atrybutem
async
, którym zajmiemy się nieco później, nie blokująDOMContentLoaded
. - Skrypty, które są generowane dynamicznie za pomocą
document.createElement("script")
, a następnie dodawane do strony internetowej, również nie blokują tego zdarzenia.
DOMContentLoaded i styles
Zewnętrzne arkusze stylów nie wpływają na DOM, więc DOMContentLoaded
nie czeka na nie.
Ale jest pułapka. Jeśli po stylu mamy skrypt, musi on czekać, aż załaduje się arkusz stylów:
Powodem tego jest to, że skrypt może chcieć uzyskać współrzędne i inne zależne od stylu właściwości elementów, jak w powyższy przykład. Oczywiście musi czekać na załadowanie stylów.
Ponieważ DOMContentLoaded
czeka na skrypty, teraz czeka również na style przed nimi.
Wbudowane autouzupełnianie przeglądarki
Firefox, Chrome i Opera autouzupełnianie formularzy w DOMContentLoaded
.
Na przykład, jeśli strona ma formularz z loginem i hasłem, a przeglądarka zapamiętała wartości, to na DOMContentLoaded
może spróbować je wypełnić automatycznie (jeśli zostanie to zaakceptowane przez użytkownika).
Więc jeśli DOMContentLoaded
jest odkładane przez długo ładujące się skrypty, a następnie czeka na autouzupełnianie. Prawdopodobnie widziałeś to w niektórych witrynach (jeśli korzystasz z autouzupełniania przeglądarki) – pola logowania / hasła nie są automatycznie wypełniane od razu, ale pełne wczytanie strony jest opóźnione. W rzeczywistości jest to opóźnienie do zdarzenia DOMContentLoaded
.
window.onload
load
zdarzenie w obiekcie window
jest wyzwalane po załadowaniu całej strony, w tym stylów, obrazów i innych zasobów. To zdarzenie jest dostępne za pośrednictwem właściwości onload
.
Poniższy przykład poprawnie przedstawia rozmiary obrazów, ponieważ window.onload
czeka na wszystkie obrazy:
window.onunload
Gdy użytkownik opuszcza stronę, zdarzenie unload
uruchamia się na window
. Możemy tam zrobić coś, co nie wiąże się z opóźnieniem, na przykład zamknąć powiązane okna wyskakujące.
Godnym uwagi wyjątkiem jest wysyłanie danych analitycznych.
Powiedzmy, że zbieramy dane o tym, jak strona jest używane: kliknięcia myszą, przewijanie, przeglądane obszary strony itd.
Oczywiście unload
zdarzenie ma miejsce, gdy użytkownik nas opuszcza, a my chcielibyśmy zapisz dane na naszym serwerze.
Wysyła dane w tle.Przejście na inną stronę nie jest opóźnione: przeglądarka opuszcza stronę, ale nadal wykonuje sendBeacon
.
Oto jak z tego korzystać:
- Żądanie jest wysyłane jako POST.
- Możemy wysłać nie tylko ciąg znaków, ale także formularze i inne formaty, jak opisano w rozdziale Pobieranie, ale zwykle jest to obiekt z ciągami znaków.
- Dane są ograniczone do 64 kB.
Po zakończeniu żądania sendBeacon
przeglądarka prawdopodobnie opuściła już dokument, więc nie ma sposobu, aby uzyskać odpowiedź serwera (która zwykle jest pusta do celów analitycznych).
Istnieje również flaga keepalive
do wykonywania takich żądań „po lewej stronie” w metodzie pobierania dla ogólnych żądań sieciowych. Więcej informacji znajdziesz w rozdziale Fetch API.
Jeśli chcemy anulować przejście na inną stronę, nie możemy tego zrobić tutaj. Ale możemy użyć innej zdarzenie – onbeforeunload
.
window.onbeforeunload
Jeśli użytkownik zainicjował nawigację aw ay ze strony lub próbuje zamknąć okno, moduł obsługi beforeunload
prosi o dodatkowe potwierdzenie.
Jeśli anulujemy zdarzenie, przeglądarka może zapytać użytkownika, czy są pewni.
Możesz spróbować, uruchamiając ten kod, a następnie ponownie ładując stronę:
Ze względów historycznych zwrócenie niepustego ciągu również liczy się jako anulowanie wydarzenie. Jakiś czas temu przeglądarki wyświetlały to jako wiadomość, ale zgodnie ze współczesną specyfikacją nie powinny.
Oto przykład:
Zachowanie zostało zmienione , ponieważ niektórzy webmasterzy nadużyli tego modułu obsługi zdarzeń, wyświetlając mylące i irytujące komunikaty. W tej chwili stare przeglądarki mogą nadal wyświetlać to jako wiadomość, ale poza tym – nie ma możliwości dostosowania komunikatu wyświetlanego użytkownikowi.
readyState
Co się stanie, jeśli ustawimy moduł obsługi DOMContentLoaded
po załadowaniu dokumentu?
Oczywiście nigdy nie działa.
Są przypadki, kiedy nie jesteśmy pewni, czy dokument jest gotowy czy nie. Chcielibyśmy, aby nasza funkcja wykonywała się po załadowaniu DOM, czy to teraz, czy później.
Właściwość document.readyState
informuje nas o aktualnym stanie ładowania.
Istnieją 3 możliwe wartości:
-
"loading"
– dokument się ładuje. -
"interactive"
– dokument został w pełni przeczytany. -
"complete"
– dokument został w pełni odczytany i wszystkie zasoby (takie jak obrazy) są załadowane też.
Możemy więc sprawdzić document.readyState
i skonfigurować program obsługi lub natychmiast wykonać kod, jeśli jest gotowy.
Jest także zdarzenie readystatechange
, które jest wyzwalane po zmianie stanu, więc możemy wydrukować wszystkie te stany w następujący sposób:
readystatechange
to alternatywna mechanika śledzenia stanu ładowania dokumentu, pojawiła się dawno temu. W dzisiejszych czasach jest rzadko używany.
Zobaczmy pełny przepływ zdarzeń dla kompletności.
Oto dokument z <iframe>
, <img>
i programy obsługujące, które rejestrują zdarzenia:
Działający przykład znajduje się w piaskownicy.
Typowe dane wyjściowe:
liczby w nawiasach kwadratowych oznaczają przybliżony czas, w którym to się dzieje. Zdarzenia oznaczone tą samą cyfrą mają miejsce mniej więcej w tym samym czasie (± kilka ms).
-
document.readyState
staje sięinteractive
tuż przedDOMContentLoaded
. Te dwie rzeczy właściwie oznaczają to samo. -
document.readyState
staje sięcomplete
, gdy wszystkie zasoby (iframe
iimg
) są ładowane. Tutaj widzimy, że dzieje się to mniej więcej w tym samym czasie coimg.onload
(img
to ostatni zasób) iwindow.onload
. Przejście do stanucomplete
oznacza to samo, cowindow.onload
. Różnica polega na tym, żewindow.onload
zawsze działa po wszystkich innych modułach obsługiload
.
Podsumowanie
Zdarzenia wczytywania strony:
- Zdarzenie
DOMContentLoaded
uruchamia się wdocument
, gdy DOM jest gotowy. Na tym etapie możemy zastosować JavaScript do elementów.- Skrypt taki jak
<script>https://javascript.info/...</script>
lub<script src="https://javascript.info/..."></script>
blokuje DOMContentLoaded, przeglądarka czeka aby je wykonać. - Obrazy i inne zasoby mogą nadal się ładować.
- Skrypt taki jak
-
load
zdarzenie wwindow
jest wyzwalane po załadowaniu strony i wszystkich zasobów. Rzadko go używamy, ponieważ zwykle nie ma potrzeby czekać tak długo. - Zdarzenie
beforeunload
wwindow
jest wyzwalane, gdy użytkownik chce opuścić stronę. Jeśli anulujemy zdarzenie, przeglądarka zapyta, czy użytkownik naprawdę chce wyjść (np. Mamy niezapisane zmiany). - Zdarzenie
unload
w dniuwindow
uruchamia się, gdy użytkownik w końcu wychodzi, w module obsługi możemy robić tylko proste rzeczy, które nie wymagają opóźnień ani nie pytają użytkownika. Z powodu tego ograniczenia jest rzadko używany. Możemy wysłać żądanie sieciowe znavigator.sendBeacon
. -
document.readyState
to aktualny stan dokumentu, zmiany mogą być śledzone w zdarzeniureadystatechange
:-
loading
– trwa ładowanie dokumentu. -
interactive
– dokument jest analizowany, dzieje się mniej więcej w tym samym czasie coDOMContentLoaded
, ale przed nim. -
complete
– dokument i zasoby są ładowane, dzieje się mniej więcej w tym samym czasie cowindow.onload
, ale przed nim.
-