Как отложить встроенный Javascript?
У меня есть следующий код html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/blazy/1.8.2/blazy.min.js" defer></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.9.0/js/lightbox.min.js" defer></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous" defer></script>
<!-- 26 dec flexslider js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/flexslider/2.6.3/jquery.flexslider.min.js" defer></script>
<script defer>
(function($) {
$(document).ready(function() {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
});
})(jQuery);
</script>
</head>
<body>
</body>
</html>
Я получаю сообщение об ошибке, говоря, что jQuery не определен. Теперь, даже если я удалю defer из моего встроенного JS-кода, он говорит, что jQuery - это undefined. По какой-то причине я должен держать плагины jQuery в голове и держать свой JS-код в строке. Мой вопрос:
-
Почему встроенный Javascript-код не откладывается, если на нем присутствует атрибут defer
?
-
Есть ли способ подражать отложенному поведению моего встроенного кода JavaScript? Я могу поместить это в конец тега тела, если потребуется.
Ответы
Ответ 1
Загрузка скриптов в том порядке, в котором они указаны, но поскольку все они имеют атрибут defer
, все они выполняются после того, как сам документ был загружен. Поскольку defer
не влияет на теги script
, если они также не имеют тег src
, первый script, который выполняется, является вашим встроенным script. Так что в то время jQuery еще не загружен.
Вы можете решить это, по крайней мере, двумя способами:
-
Поместите свой встроенный script в файл .js
и укажите его с атрибутом src
или
-
Дождитесь загрузки документа и отложенных сценариев следующим образом:
<script>
window.addEventListener('DOMContentLoaded', function() {
(function($) {
$(document).ready(function() {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
});
})(jQuery);
});
</script>
NB: в последнем случае $(document).ready(function()
действительно не нужно, так как в то время документ уже готов, но jQuery хорош и немедленно выполнит обратный вызов.
Ответ 2
Из документов MDN:
Перенести
Этот атрибут Boolean установлен для указания браузеру, что script предназначен для выполнения после того, как документ был проанализирован, но перед запуском DOMContentLoaded
. Атрибут defer должен использоваться только для внешних скриптов.
Это называется IIFE (Expression Exited Function Expression), которое выполняется до того, как DOM доступен. Итак, в этом случае jQuery
есть undefined, потому что это не в DOM.
Ответ 3
Вы можете создать URL-адрес Base64 из script и поместить его в src!
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer>
</script>
Я построил быстрый тест, чтобы увидеть его в действии.
Вы должны увидеть предупреждение с Hello world!
последним, если defer
работает:
<script defer>
alert('Why no defer?!?');
</script>
<!-- alert('Hello world!'); -->
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer></script>
<script>
alert('Buh-bye world!');
</script>