Эта статья была впервые опубликована на github, если вам интересно, пожалуйстакликните сюда
Событие onload окна, безусловно, знакомо по детской обуви.Я считаю, что когда вы только начинаете, наиболее вероятно, что вы увидите событие загрузки.loadЧем больше контактов с событием, тем больше людей свяжется с его подругамиDOMContentLoadedсобытий, в Интернете есть много статей, знакомящих с этими двумя событиями, да它们
Объяснение не более чем следующие два
- load
Объяснение MDN:loadСледует использовать только для обнаружения полностью загруженной страницы. Событие загрузки запускается, когда ресурс и его зависимые ресурсы завершили загрузку.
Это означает, что событие нагрузки не будет запущено до тех пор, пока HTML, CSS, JS, изображения и другие ресурсы страницы не загружены.
- DOMContentLoaded
Объяснение MDN: событие DOMContentLoaded запускается, когда исходный HTML-документ полностью загружен и проанализирован, не дожидаясь окончания загрузки таблиц стилей, изображений и подфреймов.
означает HTMLскачать, разобратьСрабатывает по окончании.
После прочтения этих двух объяснений я все еще в замешательстве, я просто знаю, когда события load и DOMContentLoaded запускаются, как ученик начальной школы, читающий текст, но я все еще не понимаю, при каких обстоятельствах запускаются эти два события.
некоторые концепции
скачать/загрузить
Эти два слова выражают одно и то же значение, то есть процесс загрузки браузером ресурсов в локальный.
Разобрать
Парсинг означает преобразование элемента в другую форму определенным образом. например парсинг html. Прежде всего, должно быть понятно, что загруженное в браузер представление html представляет собой файл, содержащий строки. Браузер считывает строку из html-файла в память, извлекает и компилирует строку в соответствии с правилами html и преобразует строку в другую структуру данных, которую легко выразить. Давайте посмотрим на следующий фрагмент кода:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>只有css</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div id="div1"></div>
<link rel="stylesheet" href="./c1.css" />
<link rel="stylesheet" href="./c3.css" />
<script src="http://test.com:9000/mine/load/case2/j1.js
"></script>
<link rel="stylesheet" href="./c4.css" />
<div id="div2"></div>
</body>
</html>
Браузер скомпилирует этот HTML-файл и преобразует его в структуру, подобную следующей (другие теги в заголовке здесь опущены).
Браузер проанализирует преобразованную структуру данных сверху вниз: сначала запустит поток загрузки, расставит приоритеты и загрузит все ресурсы (обратите внимание, что это только загрузка). При этом основной поток будет парсить документ:
- При обнаружении тега script сначала заблокируйте синтаксический анализ последующего контента и проверьте, был ли загружен скрипт. Если да, выполните код.
- При обнаружении тега ссылки он не будет блокировать синтаксический анализ последующего содержимого (например, построение DOM), проверять, был ли загружен ресурс ссылки, и если да, создавать cssom.
- Когда встречается тег DOM, выполняется построение DOM, добавляя этот элемент DOM в дерево документа.
Следует отметить, что до того, как загрузка первого ресурса скрипта в теле будет завершена, браузер выполнит первый рендеринг, объединив дерево DOM и CSSOM перед тегом скрипта в дерево рендеринга и отобразив его на странице. .Это временной узел от белого экрана до первого рендеринга страницы, что более критично..
строительство ДОМ
Построение DOM означает, что все элементы DOM в документе построены в виде древовидной структуры.
Обратите внимание, что построение DOM строится сверху вниз и будет мешать выполнению js.
CSS-сборка
Объедините все ресурсы css в документе.
визуализировать дерево
Объедините дерево DOM и CSS в одно дерево рендеринга, и дерево рендеринга будет отображаться на странице в нужное время. (Например, если встречается сценарий, он не был загружен локально).
Загрузка HTML-документа и первый рендеринг страницы
Что происходит, когда мы вводим адрес страницы?
- 1. Браузер сначала загружает html-страницу, соответствующую адресу.
- 2. Браузер анализирует структуру DOM html-страницы.
- 3. Откройте поток загрузки, чтобы загрузить все ресурсы в документе в порядке приоритета.
- 4. Основной поток продолжает парсить документ и достигает головного узла.Внешние ресурсы в голове — это не что иное, как таблицы стилей внешних ссылок и js внешних ссылок.
- Если обнаружено, что есть внешняя ссылка css или внешняя ссылка js, если это внешняя ссылка js, остановить парсинг последующего контента, дождаться загрузки ресурса и выполнить его сразу после завершения загрузки. Если это внешняя ссылка css, продолжайте анализировать последующее содержимое.
- 5. Разобрать тело
В теле может быть много ситуаций, в теле могут быть только DOM элементы, а могут быть как DOM, css, js и другие ресурсы, так и js ресурсы могут асинхронно подгружать картинки, css, js и т.д. Структура DOM другая, и механизм парсинга в браузере тоже другой, об этом поговорим отдельно.
- только DOM-элементы
- Эта ситуация относительно проста: после того, как DOM-дерево построено, страница визуализируется в первый раз.
- Есть DOM элементы, внешние ссылки js.
- При парсинге на внешний js, js не был загружен на локальный, DOM перед js будет отрисовываться на странице, а js будет препятствовать построению последующего DOM, то есть последующие узлы DOM не будут добавлены в DOM документа в дереве. Поэтому, пока js не будет выполнен, мы не можем видеть DOM-элементы за js на странице.
- Есть элементы DOM, внешние ссылки css
- Внешняя ссылка css не повлияет на построение DOM за css, но будет мешать рендерингу. Проще говоря, до загрузки внешнего css страница остается пустой.
- Есть элементы DOM, внешняя ссылка js, внешняя ссылка css
- Порядок обратных ссылок js и обратных ссылок css влияет на отрисовку страницы, что особенно важно. Когда внешняя ссылка css перед js в теле не загружена, страница не будет отображаться.
- Когда внешняя цепочка css перед js в теле загружается, дерево DOM перед js и css объединяется в дерево рендеринга, и страница отображает структуру DOM перед js.
- только DOM-элементы
- 6. После анализа документа страница повторно визуализируется. Когда выполняется весь код синхронизации js, на который ссылается страница, запускается событие DOMContentLoaded.
- 7. После загрузки ресурсов изображений в html-документе и асинхронно загруженных ресурсов css, js и изображений в коде js запускается событие загрузки.
Код теста выглядит следующим образом
<body>
<!-- 白屏 -->
<div id="div1"></div>
<!-- 白屏 -->
<link rel="stylesheet" href="./c1.css" />
<!-- 白屏 -->
<link rel="stylesheet" href="./c3.css" />
<!-- 如果此时 j1.js 尚未下载到本地,则首次渲染,此时的 DOM 树 只有 div1 ,所以页面上只会显示 div1,样式是 c1.css 和 c3.css 的并集。-->
<!-- 如果此时 j1.js 已经下载到本地,则先执行 j1.js,页面不会渲染,所以此时仍然是白屏。-->
<!--下面的 js 阻塞了 DOM 树的构建,所以下面的 div2 没有在文档的 DOM 树中。 -->
<script src="http://test.com:9000/mine/load/case2/j1.js
"></script>
<!-- j1.js 执行完毕,继续 DOM 解析,div2 被构建在文档 DOM 树中,此时页面上有了div2 元素,样式仍然是 c1.css 和 c3.css 的并集 -->
<link rel="stylesheet" href="./c4.css" />
<!-- c4.css 加载完毕,重新构建render树,样式变成了 c1.css、c3.css 和 c4.css 的并集 -->
<div id="div2"></div>
<script>
// 利用 performance 统计 load 加载时间。
window.onload=function(){console.log(performance.timing.loadEventStart - performance.timing.fetchStart);}
</script>
</body>
Вы можете настроить размещение ресурсов и наблюдать за производительностью синтаксического анализа браузера.
Загрузка ресурсов в голове
- Загрузка ресурсов js в голову остановит построение следующего DOM, но не повлияет на загрузку следующих ресурсов.
- Ресурсы CSS не будут блокировать последующее построение DOM, но будут блокировать первый рендеринг страницы.
Загрузка ресурсов в тело
- Загрузка ресурсов js в тело остановит построение следующего DOM, но не повлияет на загрузку следующих ресурсов.
- Ресурсы CSS не будут блокировать последующее построение DOM, но будут блокировать первый рендеринг страницы.
Запуск события DomContentLoaded
Вышеприведенное говорит только о загрузке и рендеринге html-документов и не говорит о времени срабатывания события DOMContentLoaded. Прямой вывод состоит в том, что событие DOMContentLoadedЗапускается после загрузки html-документа и выполнения встроенного js, на который ссылается html, и кода синхронизации внешнего js..
Вы можете написать тестовый код самостоятельно и обратиться к встроенным js и js внешней цепочки для тестирования.
запуск события загрузки
Когда загружены js, css, изображения в структуре DOM страницы, а также js, css и изображения, загруженные асинхронно с помощью js, будет запущено событие загрузки.
Уведомление:
- Если код js, указанный на странице, содержит js, css и изображения, загруженные асинхронно, это повлияет на запуск события загрузки.
- Видео, аудио и флэш-память не влияют на запуск события загрузки.
Можешь попробовать в хроме.
Количество одновременных потоков загрузки ресурсов под одним и тем же доменным именем браузером, 6 для chrome.
- пара браузеровтакое же доменное имяЗагрузки до 6 одновременных загрузок. Если их больше 6, остальные будут ждать в очереди, поэтому мы сводим ресурсы к разным доменным именам, а также в полной мере используем этот механизм, загружаем необходимые ресурсы одновременно в наибольшей степени и завершаем страницу рендеринг как можно скорее.
Ключевые слова, которые следует здесь отметить:такое же доменное имя. При наличии n разных доменных имен в пределах максимального верхнего предела, установленного браузером (по умолчанию 10), может быть достигнута максимальная одновременная загрузка n * 6.
статистика производительности.
Кроме того, время, необходимое для срабатывания события загрузки и события DOMContentLoaded, можно подсчитать с помощью некоторых свойств объекта производительности, и время с точностью до наносекунд. Статистика производительности некоторых крупных компаний также в основном использует данные этого объекта для отчетности.
- connectStart: время, когда HTTP (TCP) начинает устанавливать соединение. Если это постоянное соединение, оно равно времени fetchStart.Обратите внимание, что если на транспортном уровне возникает ошибка и соединение восстанавливается, здесь отображается время начала вновь установленного соединения.
- connectEnd: время завершения установления соединения.
- domComplete: когда дерево DOM проанализировано и ресурс готов, Document.readyState становится завершенным, и будут сгенерированы события, связанные с readystatechange.
- domContentLoadedEventEnd: после завершения синтаксического анализа DOM время загрузки ресурсов на веб-странице (например, завершение загрузки и выполнения JS и CSS).
- domContentLoadedEventStart: после завершения синтаксического анализа DOM время, когда начинается загрузка ресурса на веб-странице, прежде чем будет выдано событие DOMContentLoaded.
- loadEventStart: запускается событие загрузки, то есть время, когда функция обратного вызова загрузки начинает выполняться. Примечание. Если событие загрузки не привязано, значение равно 0.
- loadEventEnd: время, когда завершается выполнение функции обратного вызова события загрузки.
- ...
Есть и другие атрибуты статистики производительности, которые вы можете изучить.
Я надеюсь, что приведенный выше контент натолкнет вас на размышления и поможет вам понять механизм загрузки документов.