Является ли $(document).ready() также готовым CSS?
У меня есть скрипт, выполняющийся на $(document).ready(), который должен вертикально выровнять блочный элемент в моем макете. 90% времени это работает без проблем. Однако за эти дополнительные 10% происходит одно из двух:
Существует очевидная задержка во времени, необходимом для центрирования, и элементы блока переходят в нужное положение. Это может быть просто связано с производительностью - так как размер страницы часто велик, и за один раз выполняется довольно много javascript.
Центрирование будет полностью испорчено, и элемент блока будет либо отталкиваться слишком далеко, либо недостаточно далеко. Похоже, что он пытался вычислить высоту, но получал неправильные измерения.
Есть ли какая-то причина, по которой при выполнении сценария в DOM-ready все правильные значения CSS не будут внедрены в DOM? (весь CSS находится в <head>
через <link>
).
Кроме того, вот сценарий, который вызывает проблему (да, он был взят прямо отсюда):
(function ($) {
// VERTICALLY ALIGN FUNCTION
$.fn.vAlign = function() {
return this.each(function(i) {
var ah = $(this).height();
var ph = $(this).parent().height();
var mh = (ph - ah) / 2;
$(this).css('margin-top', mh);
});
};
})(jQuery);
Благодарю.
5 ответов
Метод ready() больше не пытается дать какие-либо гарантии ожидания загрузки всех таблиц стилей. Вместо этого все CSS-файлы должны быть включены перед сценариями на странице. Дополнительная информация
Примечание: пожалуйста, убедитесь, что все таблицы стилей включены в ваши сценарии (особенно те, которые вызывают функцию ready). Это обеспечит правильное определение всех свойств элемента перед началом выполнения кода jQuery. Невыполнение этого требования может вызвать спорадические проблемы, особенно в браузерах на основе WebKit, таких как Safari.
Обратите внимание, что приведенное выше даже не касается фактического рендеринга CSS, поэтому вы все равно можете увидеть изменение экрана, когда ready()
пинает. Но это должно спасти вас от проблем.
На самом деле, я нахожу немного странным, что просто поместив CSS над JS, мы решим все проблемы. CSS загружается асинхронно, поэтому загрузка JS может начинаться и заканчиваться, пока CSS еще загружается. Так что, если вышеупомянутое является решением, то выполнение любого кода JS затем останавливается, пока все более ранние запросы не будут выполнены?
Я провел некоторое тестирование, и действительно, иногда JS откладывается до загрузки CSS. Я не знаю почему, потому что водопад показывает, что JS завершил загрузку задолго до завершения загрузки CSS.
См. JS Bin для ознакомления с HTML-кодом и его результатами (с 10-секундной задержкой), а также с информацией о результатах водопада на webpagetest.org. Это использует некоторый сценарий от cuzillion.com Стива Соудерса для имитации медленных ответов. В водопаде, ссылка на resource.cgi
это CSS. Итак, в Internet Explorer первый внешний JS начинает загружаться сразу после запроса CSS (но этот CSS займет еще 10 секунд). Но второе<script>
тег не выполняется до тех пор, пока не закончится загрузка CSS:
<link rel="stylesheet" type="text/css" href=".../a script that delays.cgi" />
<script type="text/javascript" src=".../jquery.min.js"></script>
<script type="text/javascript">
alert("start after the CSS has fully loaded");
$(document).ready(function() {
$("p").addClass("sleepcgi");
alert("ready");
});
</script>
Другой тест со вторым внешним JS после получения jQuery показывает, что загрузка второго JS не начинается, пока не загрузится CSS. Здесь первая ссылка на resource.cgi
это CSS, второй JS:
Перемещение таблицы стилейниже всех JS действительно показывает, что JS (включая ready
функция) запускается намного раньше, но даже тогда класс jQuery-применения, который еще неизвестен при запуске JS, правильно используется в моих быстрых тестах в Safari и Firefox. Но имеет смысл, что такие вещи, как$(this).height()
будет давать неправильные значения в это время.
Однако дополнительное тестирование показывает, что JS не является общим правилом до тех пор, пока не будет загружен ранее определенный CSS. Кажется, есть некоторая комбинация с использованием внешних JS и CSS. Я не знаю, как это работает.
Последнее замечание: поскольку JS Bin включает Google Analytics в каждый сценарий при запуске с чистого URL (например, http://jsbin.com/aqeno/, результаты теста фактически изменяются JS Bin... Похоже, что вкладка "Вывод" в редактируемом URL, например http://jsbin.com/aqeno/edit не включает в себя дополнительные функции Google Analytics и, безусловно, дает другие результаты, но этот URL сложно протестировать с помощью webpagetest.org. Ссылка на блокировку загрузок таблиц стилей в Firefox и выполнение JavaScript в IE, как указано в strager - хорошее начало для лучшего понимания, но у меня осталось много вопросов... Также обратите внимание на параллельную загрузку скриптов IE8 Стива Соудерса, чтобы сделать вещи еще более сложными (описанные выше водопады создаются с помощью IE7).
Может быть, нужно просто верить примечаниям к выпуску и документации...
Порядок CSS/JavaScript/JQuery не работает для меня, но следующее работает:
$(window).load(function() { $('#abc')...} );
DOM ready срабатывает, когда все узлы DOM доступны. Это не имеет ничего общего с CSS. Попробуйте позиционировать стиль раньше или попробуйте загрузить его по-другому.
Насколько я знаю, событие ready вызывается при загрузке DOM - это означает, что все запросы на блокировку (т.е. JS) были загружены и дерево DOM полностью построено. Состояние готовности в IE основано на более медленном триггере событий (изменение document.readyState и DOMContentLoaded), чем в большинстве других браузеров, поэтому выбор времени также зависит от браузера.
Существование неблокирующих запросов (таких как CSS и изображения) полностью асинхронно и не связано с состоянием готовности. Если вы находитесь в положении, когда вам требуются такие ресурсы, вы должны зависеть от старого доброго события onload.
Согласно HTML5, DOMContentLoaded - это простое событие, готовое к DOM, без учета таблиц стилей. Однако алгоритм синтаксического анализа HTML5 требует, чтобы браузеры откладывали выполнение сценариев до тех пор, пока не будут загружены все предыдущие таблицы стилей. ( DOMContentLoaded и таблицы стилей)
- IE и Firefox заблокировали все последующее выполнение скрипта до загрузки таблиц стилей
- Webkit заблокировал последующее выполнение только для внешних скриптов (
<script src>
) - Opera не блокировала последующее выполнение ни одного скрипта
Все современные браузеры теперь поддерживают DOMContentLoaded (2017), поэтому они, возможно, уже стандартизировали это поведение.