2016-12-30 143 views
11

我有以下的html代码:如何推迟内嵌Javascript?

<!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。现在,即使我从我的内联JS代码中删除延迟,它说jQuery是未定义的。出于某种原因,我必须保持jQuery插件的头脑,并保持我的JS代码内联。我的问题是:

  1. 为什么不内联Javascript代码得到延期时defer属性存在就可以了?

  2. 有没有一种方法可以模仿我的内嵌Javascript代码的延迟行为?如果需要,我可以将它放在身体标记的末尾。

+3

您的在线移动的JavaScript外部文件,然后推迟它,以及:) – mike510a

+0

还可以通过编程内嵌的外部JavaScript,如果你不想使用HTML5 – mike510a

+0

@ mike510a由于某些原因,我无法将其放入外部文件。它由php生成,我不知道关于PHP,所以我不能更改该代码。 – user31782

回答

33

脚本按照它们指定的顺序加载,但由于它们都具有defer属性,它们都在文档本身加载后执行。由于deferscript标记没有影响,除非它们也具有src标记,所执行的第一个脚本就是您的内联脚本。所以当时jQuery尚未加载。

可以在至少两种方式解决这个问题:

  • 把你的嵌入式脚本在.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> 
    

注意:在后一种情况下,$(document).ready(function()实际上是不必要的,因为那时文档已经准备好了 - 但jQuery很好,并且会立即执行回调。

+0

感谢您的回答。是否确定在加载所有延迟的脚本后,DOMContentLoaded事件会触发? – user31782

+0

是的,这是肯定的。 – trincot

+0

哦,是的!这就是MDN文档所说的...... – user31782

2

从MDN文档:

延迟
此布尔属性被设置为指示脚本意味着将要执行的文件已经被解析后,浏览器,但发射前DOMContentLoadeddefer属性只能用于外部脚本。

这就是所谓的IIFE (立即调用函数表达式),它被DOM前执行可用。因此,在这种情况下,jQuery未定义,因为它不在DOM中。

+0

但是,如何处理内联脚本?为什么他们不遵循声明的顺序呢? – user31782

+0

@ user31782其原因在于'(jQuery)'部分要求'jQuery'在其被访问之前被定义 - 并且推迟脚本意味着在所有其他事物(包括内联代码)之后才定义该脚本中的任何东西 – mike510a

+0

这是因为IIFE语法。它立即运行,它不会等待dom被加载。 – Jai

2

你可以在脚本中创建一个Base64 URL并将其放入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>

这样做是手动有点费力,所以如果你通过某种方式编写HTML的奢侈品(车把,角度等),那么这会有很大的帮助。

我目前使用:

<script src="data:text/javascript;base64,{{base64 "alert('Hello world!');"}}" 
     defer> 
</script> 
+0

这太可怕了...但辉煌 – PaulSkinner