Я хочу запустить javascript до того, как загрузится вся страница. Это возможно? Или код начинает выполняться </html>
?
javascript
html
пикник
источник
источник
Ответы:
Не только можете , но и должны приложить особые усилия, чтобы не делать этого, если не хотите. :-)
Когда браузер встречает классический
script
тег при синтаксическом анализе HTML, он прекращает синтаксический анализ и передает его интерпретатору JavaScript, который запускает сценарий. Анализатор не продолжает работу до завершения выполнения сценария (поскольку сценарий может выполнятьdocument.write
вызовы для вывода разметки, которую синтаксический анализатор должен обработать).Это поведение по умолчанию, но у вас есть несколько вариантов отсрочки выполнения скрипта:
Используйте модули JavaScript.
type="module"
Сценарий откладывается до тех пор , HTML не был полностью разобран и первоначальный DOM создан. Это не основная причина использования модулей, но одна из причин:Код будет извлечен (если он отдельный) и проанализирован параллельно с синтаксическим анализом HTML, но не будет запущен, пока не будет выполнен синтаксический анализ HTML. (Если код вашего модуля является встроенным, а не в собственном файле, он также откладывается до завершения синтаксического анализа HTML.)
Этого не было, когда я впервые написал этот ответ в 2010 году, но здесь, в 2020 году, все основные современные браузеры поддерживают модули изначально, и если вам нужно поддерживать старые браузеры, вы можете использовать такие комплекты, как Webpack и Rollup.js.
Используйте
defer
атрибут в классическом теге скрипта:Как и в случае с модулем, код
my-code.js
будет извлечен и проанализирован параллельно с синтаксическим анализом HTML, но не будет запущен, пока не будет выполнен анализ HTML. Но ,defer
не работает с встроенным содержанием сценария, только с внешними файлами с помощью ссылкиsrc
.Я не думаю, что это то, что вы хотите, но вы можете использовать
async
атрибут, чтобы указать браузеру, что нужно извлекать код JavaScript параллельно с синтаксическим анализом HTML, но затем запустить его как можно скорее, даже если синтаксический анализ HTML не завершен. . Вы можете прикрепить его кtype="module"
тегу или использовать вместоdefer
классическогоscript
тега.Поместите
script
тег в конец документа, непосредственно перед закрывающим</body>
тегом:Таким образом, даже если код запускается, как только он встречается, все элементы, определенные указанным выше HTML, существуют и готовы к использованию.
Раньше это вызывало дополнительную задержку в некоторых браузерах, потому что они не начинали получать код до тех пор, пока
script
не встретился тег, но современные браузеры просматривают вперед и начинают предварительную выборку. Тем не менее, на данный момент это уже третий вариант, оба модуля иdefer
являются лучшими вариантами.Спецификации имеют полезную схему , показывающую сырой
script
тег,defer
,async
,type="module"
, иtype="module" async
и сроки , когда код JavaScript извлекается и запустить:Вот пример поведения по умолчанию, необработанный
script
тег:(Подробнее об этом коде см. В моем ответе
NodeList
.)Когда вы запустите это, вы увидите «Параграф 1» зеленым, а «Параграф 2» - черным, потому что сценарий работал синхронно с синтаксическим анализом HTML, и поэтому он нашел только первый абзац, а не второй.
Напротив, вот
type="module"
сценарий:Обратите внимание, как они оба теперь зеленые; код не запускался, пока не был завершен анализ HTML. То же самое будет и
defer
script
с внешним содержимым (но не со встроенным содержимым).(Там не было никакой необходимости в
NodeList
проверке там , потому что любой современный браузер поддерживает модули уже естьforEach
наNodeList
.)В этом современном мире нет реальной ценности в
DOMContentLoaded
случае «готовой» функции, которую PrototypeJS, jQuery, ExtJS, Dojo и большинство других предоставили в свое время (и все еще предоставляют); просто используйте модули илиdefer
. Даже когда-то не было особых причин для их использования (и они часто использовались неправильно, задерживая презентацию страницы, пока вся библиотека jQuery была загружена, потому что онаscript
была в,head
а не после документа), что некоторые разработчики отметили Google рано обратил внимание. Это также было одной из причин, по которой YUI рекомендовал ставить скрипты в концеbody
, снова в тот же день.источник
<body onload="doIt()>"
.load
событие происходит очень поздно в цикле загрузки страницы, почти никогда не рекомендуется ждать, чтобы запустить свой JavaScript до этого момента. Но да, это вариант. Кстати, я пересмотрел ответ на 2020 год.document.addEventListener('DOMContentLoaded', function(){ //doyour stuff })
Вы можете запустить код javascript в любое время. AFAIK он выполняется в тот момент, когда браузер достигает тега <script>, в котором он находится. Но вы не можете получить доступ к элементам, которые еще не загружены.
Поэтому, если вам нужен доступ к элементам, вы должны дождаться загрузки DOM (это не означает, что загружается вся страница, включая изображения и прочее. Это всего лишь структура документа, которая загружается намного раньше, поэтому вы обычно выигрываете. не замечаю задержки), используя
DOMContentLoaded
событие или функции как$.ready
в jQuery.источник