script元素
将JavaScript
插入HTML的主要方法是使用<script>
标签。
script元素内部的代码从上而下依次执行。
在引入多个script元素的时候,浏览器会按照script元素在页面中的先后顺序进行解析,当上一个解析完成时,才会进行下一个script元素中的内容。
在HTML中使用JavaScript的两种方法:
// 第一种方法:直接在标签内使用javascript即可
<script>
console.log('Hello World!')
</script>
// 第二种方法:引用外部文件
<script src="examplae.js"></script>
script元素常用属性
- src:可选,用于引用外部javascript文件
- type:可选,编写代码使用的脚本语言类型(也称MIME类型),默认值为
text/javascript
- async:可选,异步加载脚本,只对外部文件有效
- defer:可选,延迟加载脚本,只对外部文件有效
延迟加载脚本和异步加载脚本
- 延迟加载脚本
defer
在script元素中设置了defer
属性,表示脚本会被延迟到整个页面都解析完毕后再运行(也就是浏览器解析到结束的</html>
标签后才执行),推迟的脚本原则上按照它们被列出的次序执行。
如下面代码所示: example2.js
会在example1.js
之后执行,两者都会在 DOMContentLoaded
事件之前执行
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script defer src="example1.js"></script>
<script defer src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
- 异步加载脚本
async
在script
元素中定义了async
属性,表示脚本不需要等待其他脚本,同时也不阻塞文档渲染。(也就是告诉浏览器,不必等脚本下载和执行完后再加载页面,同样也不必等到该异步脚本下载和执行后再加载其他脚本)。异步脚本保证会在页面的load
事件前执行,但可能会在DOMContentLoaded
之前或之后。
如下面代码所示: example2.js
可能会先于example1.js
执行,所以在使用async属性时,要避免两个js相互依赖。
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script defer src="example1.js"></script>
<script defer src="example2.js"></script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
- DOMContentLoaded事件会在DOM树构建完成后立即触发,而不用等待图片、js文件、css文件或其他资源加载完成。
- load事件会在整个页面(包括所有外部资源如图片、js文件和css文件)加载完成后触发。
动态加载脚本
除了<script>
标签,通过想DOM中动态添加script元素同样指定脚本。只要创建一个script元素并将其添加到DOM即可。
let script = document.createElement('script');
script.src = 'example.js';
document.body.appendChild(script);
默认情况下,以这种方式创建的<script>
元素是以异步方式加载的,相当于添加了async属性。
这样做可能会有一些问题:所有浏览器都支持createElement()方法,但并不是所有浏览器都支持async属性。因此,如果要统一动态脚本的加载行为,可以明确将其设置为同步加载:
let script = document.createElement('script');
script.src = 'example.js';
script.async = false;
document.body.appendChild(script);
以这种方式获取的资源对浏览器预加载器时不可见的,要想让预加载器知道这些动态请求文件的存在,可以在文档头部显示声明它们:
<link rel="preload" href="example.js">
思考问题
为何要把js放在body最下面?
浏览器在解析到标签时才开始渲染页面,若把所有js文件都放在里,必须等到全部js代码被下载、解析和执行完成后,才能呈现页面的内容,这会导致浏览器窗口中很长一段时间是一片空白,影响用户体验。