Я не уверен, правильно ли я понял ваш вопрос, но в случае 1, когда синтаксический анализатор начинает выполнение сценария, DOMContentLoaded еще не запускается и все еще анализирует остальную часть документа. Пока вы вызываете focus
на elemB
, вы немедленно запускаете поток макета.
В случае 2 функция onClick
вообще не вызывается, пока вы не щелкнете по самому документу. Вы можете убедиться в этом, включив "Paint Flashing" на предоставленной вами скрипке. Ввод станет зеленым только при нажатии.
Тогда как в первом случае вы видите краткую вспышку ввода при запуске (это ваш вызов .focus), а затем весь documentElement (в DOMContentLoaded).
Во втором случае у вас только один раз мигает весь documentElement (на DOMContentLoaded, при условии, что ничто другое не вызывает событие перекомпоновки/перерисовки при загрузке), а затем только элемент ввода один раз за щелчок.
PS:
Теперь, насколько я вижу, я попробовал ваши 2 случая на моей локальной машине, и, что интересно, в вашем первом случае я вижу действия 2 layout сразу после DOMContentLoaded.
Однако если я закомментирую строку elementB.focus();
из вашего случая 1 и запишу снова, я снова увижу 2 действия макета.
Насколько я понимаю, браузер будет выполнять 2 операции макета при запуске, как только он начнет анализировать тело, а затем один раз вокруг DOMContentLoaded. И если какой-либо синхронный принудительный сброс макета выполняется с помощью javascript (путем вызова любого из методов/свойств, перечисленных в вашей ссылке), браузер попытается пакетировать эти операции.
Чтобы проверить это поведение, я изменил ваш 1-й случай, как показано ниже:
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="text" style="position:relative;top:0px;">
<script type="text/javascript">
var elementB = document.querySelector('input');
elementB.focus();
</script>
<script async="true">
setTimeout(function(){
elementB.style.top = parseInt(elementB.style.top) + 5 + "px";
},500)
</script>
</body>
</html>
Теперь произойдет то, что у вас будет третье действие макета сразу после (~ 500 мс) события загрузки (асинхронность не нужна). Но если бы вы сделали setTİmeout 0 мс, вы снова получили бы 2 действия макета! (поведение очереди микрозадач может быть не гарантировано, если вы видите 3 макета, чтобы принудительно синхронизировать макет, удалите атрибут async и обертку setTimeout внутри второго тега script). Итог: Итак, браузер выполняет пакетную обработку, или, по крайней мере, это то, что я вижу в этом примере.
Что касается вашего второго случая, когда я записываю его так, как вы разместили, правильно, что я не вижу активности макета (2 макета, как и раньше). Но то, что я вижу, — это последовательный пересчет стиля + обновление дерева макета + отрисовка после каждого события. Это заставляет меня думать, что после обновления дерева макета, если удаление макета не требуется, оно не пересчитывается. Чтобы проверить это поведение, я изменил ваш второй скрипт, как показано ниже:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input type="text" style="position:relative;top:0px;">
<script type="text/javascript">
var elementB = document.querySelector('input');
function onClick() {
elementB.focus();
elementB.style.top = parseInt(elementB.style.top) + 5 + "px";
}
document.addEventListener('click', onClick);
</script>
</body>
</html>
Здесь каждый раз, когда вы щелкаете документ, поле ввода перемещается вниз на 5 пикселей. Если вы запишете в течение 10 секунд несколько кликов, вы увидите много обновления дерева макета + перерисовки И уничтожения макета. Это заставляет меня думать, что удаление макета выполняется после обновления дерева макета, если это необходимо.
ВЫВОД (могу ошибаться)
- Браузер попытается выполнить пакетную обработку макета во время синтаксического анализа HTML.
- element.focus вызовет перерисовку + обновление дерева макета, но уничтожение макета не гарантируется (по крайней мере, из этих примеров)
person
ibrahim tanyalcin
schedule
23.04.2018