一般来说开发网页时,我们喜欢将HTML文本和JS以及CSS分开,各自为独立文件,这样有助于我们日后修改或扩展代码,代码更有条理性。所以不可避免的要在HTML文件中嵌入对应CSS和JS文件。接下来我们来讨论一下嵌入JS文件的方法。
首先想到的方法就是将JS嵌入在header里如下代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="asset/app.js"></script>
</head>
<body>
<div class="menubar">...</div>
<p></p>
</body>
</html>
<script src="asset/app.js"></script> 这段代码被放在了header段的末尾。当我们加载这段HTML的时候,流程图是这样的
从流程图上我们看出来一些端倪,当我们开始解析HTML到头部时,真正body还没被执行,也就是body里的元素,class 或者id都没加载进来呢,这个时候咱们就开始执行app.js的话会报错,因为此JS是依赖于这个HTML的,比如说在class为menubar里做了监听,但menubar还未被加载。
这时候咱们提出了解决方法,也就是方法二:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="menubar">...</div>
<p></p>
<script src="asset/app.js"></script>
</body>
</html>
咱们把script 语句放在了body代码框的最后,这样一来执行的流程就变成了:
可以看出来这个流程不会有错误出现,比竟HTML已经解析完全了,再执行app.js不会有问题,但可不可以优化呢?为什么一定要解析后再加载app.js,咱们边解析边加载不好吗?
这样一来我们的第三种方法呼之欲出了:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="asset/app.js" defer></script>
</head>
<body>
<div class="menubar">...</div>
<p></p>
</body>
</html>
我们在第一个方法的基础上加了一个defer 的关键字,此关键字便让流程图变成了:
当解析HTML遇到script 于 defer的组合时,浏览器开始继续解析HTML同时加载app.js,解析完app.js并不会立即执行,而是等解析完HTML之后再执行。这样效率就高出不少。
此时,我们的小伙伴们可能还有其他需求,比如说,我加载的这JS本身跟HTML页面没有关系,这个JS就是要立刻告诉一下服务器,有人调用我了。基于这种情况,小伙伴们想要的流程图应该是:
也就是说还是要解析与加载JS同时进行,但与第三种方法不同的是,只要加载JS完成就中断解析HTML并开始执行JS,执行JS完成后继续解析HTML剩下的部分。
具体到代码,只要把关键字改成async 即可:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script src="asset/app.js" async></script>
</head>
<body>
<div class="menubar">...</div>
<p></p>
</body>
</html>
到此嵌入JS的四种方法便讲完了,顺便加个餐,小知识,如果是把JS代码直接写在HTML里,那么defer与async这两个关键字就完全没有用啦:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>demo</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script async>
alert("async and defer is useless at this point")
</script>
</head>
<body>
<div class="menubar">...</div>
<p></p>
</body>
</html>