脚本调用:
最常见的问题就是:HTML 元素是按其在页面中出现的次序调用的,如果用 JavaScript 来管理页面上的元素,若 JavaScript 加载于想操作的 HTML 元素之前,则代码将出错。
JavaScript 在文档头部,解析 HTML 文档体之前加载并执行。这样做是有隐患的,需要使用一些结构来避免错误发生。
1.内部JavaScript,使用了以下结构:
document.addEventListener("DOMContentLoaded", () => {
// …
});
这是一个事件监听器,它监听浏览器的 DOMContentLoaded
事件,其标志了 HTML 文档体完全加载和解析。该代码块中的 JavaScript 在事件被触发后才会运行,因此避免了错误。
2.外部JavaScript,使用了 JavaScript 的一项现代技术(defer
属性)来解决这一问题,它告知浏览器在遇到 <script>
元素时继续下载 HTML 内容。
<script src="script.js" defer></script>
上述情况下,脚本和 HTML 将一并加载,代码将顺利运行。
解决此问题的旧方法是:把脚本元素放在文档体的底端(也就是 </body>
标签之前,与之相邻),这样脚本就可以在 HTML 解析完毕后加载了。此方案的问题是:只有在所有 HTML DOM 加载完成后才开始脚本的加载/解析过程。对于有大量 JavaScript 代码的大型网站,可能会带来显著的性能损耗。
即:
src里面存放的js文件路径(相对于html文件存在的路径)
async 和 defer:
1.
功能:
解决
脚本阻塞问题。
2.介绍:
async:浏览器遇到 async
脚本时不会阻塞页面渲染,而是直接下载然后运行。但是,一旦下载完成,脚本就会执行,从而阻止页面渲染。脚本的运行次序无法控制。当页面的脚本之间彼此独立,且不依赖于本页面的其他任何脚本时,async
是最理想的选择。
defer:使用 defer
属性加载的脚本将按照它们在页面上出现的顺序加载。在页面内容全部加载完毕之前,脚本不会运行,如果脚本依赖于 DOM 的存在(例如,脚本修改了页面上的一个或多个元素),这一点非常有用。
3.例子:
比如,如果你的页面要加载以下三个脚本:
<script async src="js/vendor/jquery.js"></script>
<script async src="js/script2.js"></script>
<script async src="js/script3.js"></script>
三者的调用顺序是不确定的。jquery.js
可能在 script2
和 script3
之前或之后调用,如果这样,后两个脚本中依赖 jquery
的函数将产生错误,因为脚本运行时 jquery
尚未加载。
async
应该在有大量后台脚本需要加载,并且只想尽快加载到位的情况下使用。
解决这一问题可使用 defer
属性,脚本将按照在页面中出现的顺序加载和运行:
<script defer src="js/vendor/jquery.js"></script>
<script defer src="js/script2.js"></script>
<script defer src="js/script3.js"></script>
添加 defer
属性的脚本将按照在页面中出现的顺序加载,因此第二个示例可确保 jquery.js
必定加载于 script2.js
和 script3.js
之前,同时 script2.js
必定加载于 script3.js
之前。在页面内容全部加载完成之前,它们不会运行。
小结:
async
和defer
都指示浏览器在一个单独的线程中下载脚本,而页面的其他部分(DOM 等)正在下载,因此在获取过程中页面加载不会被阻塞。async
属性的脚本将在下载完成后立即执行。这将阻塞页面,并不保证任何特定的执行顺序。- 带有
defer
属性的脚本将按照它们的顺序加载,并且只有在所有脚本加载完毕后才会执行。 - 如果脚本无需等待页面解析,且无依赖独立运行,那么应使用
async
。 - 如果脚本需要等待页面解析,且依赖于其他脚本,调用这些脚本时应使用
defer
,将关联的脚本按所需顺序置于 HTML 的相应<script>
元素中。