Chcę uruchomić trochę javascript przed załadowaniem całej strony. czy to możliwe? A może kod zaczyna się wykonywać </html>
?
javascript
html
piknik
źródło
źródło
Odpowiedzi:
Nie tylko może ci, ale trzeba dołożyć szczególnych starań nie do zrobienia, jeśli nie chcą. :-)
Gdy przeglądarka napotyka klasyczny
script
tag podczas analizowania kodu HTML, zatrzymuje przetwarzanie i przekazuje go interpreterowi JavaScript, który uruchamia skrypt. Parser nie kontynuuje, dopóki wykonanie skryptu nie zostanie zakończone (ponieważ skrypt możedocument.write
wywoływać znaczniki wyjściowe, które powinien obsługiwać parser).To jest domyślne zachowanie, ale masz kilka opcji opóźnienia wykonania skryptu:
Użyj modułów JavaScript.
type="module"
Skrypt jest odroczone do momentu HTML został w pełni analizowany i początkowy DOM tworzone. To nie jest główny powód używania modułów, ale jest to jeden z powodów:<script type="module" src="./my-code.js"></script> <!-- Or --> <script type="module"> // Your code here </script>
Kod zostanie pobrany (jeśli jest oddzielny) i przeanalizowany równolegle z analizą HTML, ale nie zostanie uruchomiony, dopóki nie zostanie zakończona analiza HTML. (Jeśli kod modułu jest wbudowany, a nie we własnym pliku, jest również odroczony do zakończenia analizowania kodu HTML).
Nie było to dostępne, kiedy po raz pierwszy napisałem tę odpowiedź w 2010 roku, ale tutaj w 2020 roku wszystkie główne nowoczesne przeglądarki natywnie obsługują moduły, a jeśli potrzebujesz obsługiwać starsze przeglądarki, możesz użyć pakietów, takich jak Webpack i Rollup.js.
Użyj
defer
atrybutu w klasycznym tagu skryptu:<script defer src="./my-code.js"></script>
Podobnie jak w przypadku modułu, kod
my-code.js
zostanie pobrany i przeanalizowany równolegle z analizą HTML, ale nie zostanie uruchomiony, dopóki nie zostanie zakończona analiza HTML. Ale ,defer
nie działa z inline treści skryptu, tylko z plików zewnętrznych poprzez odwołaniesrc
.Nie sądzę, że to, co pan chce, ale można użyć
async
atrybutu poinformować przeglądarkę, aby pobrać kod JavaScript równolegle z parsowania HTML, ale następnie uruchomić go jak najszybciej, nawet jeśli parsowania HTML nie jest kompletna . Możesz umieścić go natype="module"
tagu lub użyć go zamiastdefer
klasycznegoscript
tagu.Umieść
script
tag na końcu dokumentu, tuż przed</body>
tagiem zamykającym :<!doctype html> <html> <!-- ... --> <body> <!-- The document's HTML goes here --> <script type="module" src="./my-code.js"></script><!-- Or inline script --> </body> </html>
W ten sposób, nawet jeśli kod jest uruchamiany natychmiast po jego napotkaniu, wszystkie elementy zdefiniowane w HTML powyżej istnieją i są gotowe do użycia.
Kiedyś powodowało to dodatkowe opóźnienie w niektórych przeglądarkach, ponieważ nie zaczęły one pobierać kodu, dopóki
script
nie napotkano tagu, ale nowoczesne przeglądarki skanują do przodu i rozpoczynają pobieranie wstępne. Mimo to jest to trzeci wybór w tym momencie, oba moduły idefer
są lepszymi opcjami.Spec jest użyteczny schemat przedstawiający surowego
script
tagdefer
,async
,type="module"
itype="module" async
i taktowanie, gdy kod JavaScript jest pobrana i prowadzony:Oto przykład domyślnego zachowania, surowy
script
tag:.found { color: green; }
<p>Paragraph 1</p> <script> if (typeof NodeList !== "undefined" && !NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; } document.querySelectorAll("p").forEach(p => { p.classList.add("found"); }); </script> <p>Paragraph 2</p>
(Zobacz moją odpowiedź tutaj, aby uzyskać szczegółowe informacje na temat tego
NodeList
kodu).Po uruchomieniu tego zobaczysz „Akapit 1” na zielono, ale „Akapit 2” jest czarny, ponieważ skrypt działał synchronicznie z analizą kodu HTML, więc znalazł tylko pierwszy akapit, a nie drugi.
W przeciwieństwie do tego, oto
type="module"
skrypt:.found { color: green; }
<p>Paragraph 1</p> <script type="module"> document.querySelectorAll("p").forEach(p => { p.classList.add("found"); }); </script> <p>Paragraph 2</p>
Zwróć uwagę, że oboje są teraz zielone; kod nie działał, dopóki nie zakończyła się analiza HTML. Byłoby to również prawdą w przypadku elementu
defer
script
z treścią zewnętrzną (ale nie z treścią wbudowaną).(Nie było potrzeby
NodeList
sprawdzania w tym miejscu, ponieważ każda nowoczesna przeglądarka obsługująca moduły już maforEach
włączoneNodeList
.)We współczesnym świecie nie ma prawdziwej wartości w
DOMContentLoaded
przypadku „gotowej” funkcji, którą PrototypeJS, jQuery, ExtJS, Dojo i większość innych dostarczały w ciągu dnia (i nadal zapewniają); po prostu użyj modułów lubdefer
. Nawet w tamtych czasach nie było zbyt wiele powodów, aby ich używać (i często były używane nieprawidłowo, wstrzymując prezentację strony, podczas gdy cała biblioteka jQuery była ładowana, ponieważscript
znajdowała się whead
dokumencie zamiast za), coś, co niektórzy programiści Google zgłosił się wcześnie. To również był jeden z powodów, dla których YUI zalecił umieszczenie skryptów na końcubody
tego dnia.źródło
<body onload="doIt()>"
.load
Zdarzenie ma miejsce bardzo późno w cyklu ładowania strony, prawie nigdy nie jest najlepszą praktyką czekanie z uruchomieniem JavaScript do tego czasu. Ale tak, jest to opcja. Przy okazji, przerobiłem odpowiedź na rok 2020.document.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
Możesz uruchomić kod javascript w dowolnym momencie. AFAIK jest to wykonywane w momencie, gdy przeglądarka osiągnie znacznik <script>, w którym się znajduje. Ale nie masz dostępu do elementów, które nie zostały jeszcze załadowane.
Więc jeśli potrzebujesz dostępu do elementów, powinieneś poczekać, aż DOM zostanie załadowany (nie oznacza to, że załadowana zostanie cała strona, w tym obrazy i inne rzeczy. To tylko struktura dokumentu, który jest ładowany znacznie wcześniej, więc zwykle wygrywasz nie zauważyłem opóźnienia), używając
DOMContentLoaded
zdarzenia lub funkcji takich jak$.ready
w jQuery.źródło