JavaScript 引入方式
上一篇 JavaScript 是什么 了解了 JavaScript 的能力,这一篇学习怎么把 JavaScript 代码放进网页。一共有三种方式,行内、内嵌、外部文件,各有适用场景。
行内方式
行内方式是把代码直接写在 HTML 标签的属性里,最常见的是 onclick 属性。
<button onclick="alert('你好')">点我</button>
点击按钮会弹出一个提示框。这种写法简单直接,但基本只在演示里出现,不推荐在真实项目使用。原因包括
- 代码和结构耦合在一起,HTML 和 JavaScript 混在一处,后期难维护。
- 难以复用,每个按钮都要写一遍,改动要逐处修改。
- 无法写稍长一点的逻辑,代码一多就拥挤不堪。
真实项目里,行为应该和结构分离,就像 CSS 不写在标签里一样。
内嵌方式
内嵌方式是用 script 标签把代码写在页面里,通常放在 head 或 body 中。
<!DOCTYPE html>
<html lang="zh-CN">
<body>
<script>
console.log('页面加载了');
</script>
</body>
</html>
打开页面后,控制台会输出”页面加载了”。内嵌适合页面独有、量不大的代码,比如页面初始化逻辑。缺点是不能复用,其他页面想用同样代码只能再复制一份。
外部文件方式
外部文件方式把代码写在一个独立的 .js 文件里,再用 script 标签引入。
<script src="app.js"></script>
app.js 内容如下
console.log('来自外部文件的输出');
这是实际项目最推荐的方式,优点包括
- 可复用。同一个文件可以被多个页面引入。
- 可缓存。浏览器会把文件缓存下来,页面二次访问不用重新下载。
- 便于维护。代码集中管理,和 HTML 结构彻底分离。
注意 script 标签引入外部文件时中间不能写代码,写了也会被忽略。
为什么放在 body 结束标签前面
细心的读者会发现,教程示例里 script 都放在 body 结束标签之前,这是有意为之。
浏览器解析 HTML 是自上而下的,遇到 script 标签会停下来,先下载并执行完脚本,再继续解析后面的结构。如果脚本放在 head 里且执行耗时,用户会看到页面长时间空白。
把 script 放在 body 结束标签前,页面结构已经解析完,脚本执行时页面已经渲染出来了,用户感知的加载速度更快。这是最稳妥的传统做法。
defer 和 async 简介
除了调整位置,现代写法还有两个属性可以控制外部脚本的加载时机,defer 和 async。它们都是异步加载方式,意思是下载脚本不阻塞 HTML 解析,区别在执行时机。
<script src="app.js" defer></script>
<script src="app2.js" async></script>
- defer 表示等文档解析完成后执行,多个 defer 脚本保持声明顺序。
- async 表示下载完立即执行,不保证顺序,也不等文档解析完成。
两者都不适用于内嵌脚本,只对外部文件生效。新手阶段记住 defer 更常用、行为更可预期就够了,具体取舍后面遇到再深入。
完整示例
综合练习一下,写一个完整页面,包含按钮、内嵌脚本和外部文件。文件结构如下
study/
index.html
app.js
index.html 内容
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>JS 引入方式示例</title>
</head>
<body>
<h1>JavaScript 引入方式</h1>
<button id="btn">点我</button>
<script>
const message = '内嵌脚本输出的信息';
console.log(message);
</script>
<script src="app.js"></script>
</body>
</html>
app.js 内容
console.log('外部脚本输出的信息');
在浏览器打开 index.html,按 F12 打开控制台,会依次看到两行输出,一行来自内嵌脚本,一行来自外部文件。页面先渲染出标题和按钮,再执行脚本,顺序符合预期。
小结
- 三种引入方式包括行内、内嵌、外部文件,外部文件最推荐。
- 行内写在标签属性里,代码和结构耦合,不推荐。
- script 放 body 结束标签前,是因为脚本执行会阻塞 HTML 解析,先把页面结构渲染出来。
- defer 等文档解析完成后执行且保持顺序,async 下载完立即执行,都只对外部脚本有效。
- 完整页面示例演示了内嵌脚本和外部文件同时工作的写法。