HTML 中 JavaScript 的加载方式

HTML中 JavaScript 的加载方式


前言

相信各位前端的小伙伴都用过script元素,今天我们就来好好聊一聊它。


script元素

将JavaScript插入HTML的主要方法是使用〈〉元素,有下列8个属性

属性名状态描述
async可选表示应该立即下载脚本,但不能阻止其他页面动作,只对外部脚本文件有效
charset可选使用src属性指定的代码字符集(很少用,大部分浏览器不在乎)
crossorigin可选配置相关请求的cors设置,默认不用
defer可选表示在文档解析和显示完成后再执行脚本,只对外部脚本文件有效
integrityr可选允许比对接收道德资源和指定的加密签名以验证子资源的完整性,若接收子资源的加密签名与属性指定签名不匹配,则页面报错
language废弃最初用于表示代码块中的脚本语言
src可选表示要执行的代码的外部文件
type可选表示代码块中脚本语言的内容属性

src的优先级高于行内代码:使用了src属性的script元素,如果再在标签内包含其它javascript代码,会忽略行内代码。

<script src="xxx">
// 代码无效
function fn() {}
</script>

script 标签位置

head 标签内

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    // ···js代码···
  </script>
</head>
<body>
</body>
</html>

但是这样意味着必须把所有 javascript 代码都下载、解析和解释完成后,才能开始渲染页面。当 javascript 代码很多的时候,会导致明显的渲染延迟

body 标签中页面内容后面

因为放在 head 标签内有如上渲染延迟问题,所以可以放在 body 标签中页面内容后面,如下所示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div>
    <!-- 页面元素 -->
  </div>
  <script>
    // ···js代码···
  </script>
</body>
</html>

但是这样也会有问题无法复用逻辑,例如:我在 A 页面用到了加法逻辑,在 B 页面用到了相同的逻辑,但是由于 javascript 代码写在每个页面的 html 文件内,所以我不得不在两个页面写两段重复的代码,当这样的代码越来越多时,就会影响加载 javascript 代码的效率,

引入外部 javascript 代码

将 javascript 代码单独写在 js 文件内,哪个页面使用就引入该文件。

src工作原理

<script src="http://www.somewhere.com/file/js"></script>

当浏览器在解析这个资源的时候,会向 src 属性指定的路径发送一个 get 请求,以取得相应的资源,src 不受同源策略限制,jsonp 跨域就利用这个特性。

引入外部 javascript 代码的方式

推迟执行脚本

defer属性。这个属性表示会立即下载 src引入的资源文件(不会阻断解析HTML),当页面解析完毕后,再执行脚本。当同时有多个script元素使用了该属性,会按照它们出现的顺序执行

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="test1.js" defer></script>
  <script src="test2.js" defer></script>
  <title>Document</title>
</head>
<body>
</body>
</html>

例如上面的结构,在页面加载完成后执行外部资源文件时会先执行test1.js再执行test2.js.

异步执行脚本

async属性:这个属性表示会立即下载 src引入的资源文件,下载完成后立即执行,可能会阻断HTML解析,与defer不同的是当同时有多个script元素使用了该属性,不能保证会按照它们出现的顺序执行。因此,使用该属性重点在于引入的资源文件之间没有依赖关系。

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="test1.js" async></script>
  <script src="test2.js" async></script>
  <title>Document</title>
</head>
<body>
</body>
</html>

例如上面的结构,在页面加载完成后执行外部资源文件时也许会先执行test2.js再执行test1.js.

动态加载脚本

// 创建script
let script = document.createElement('script');
// 设置src属性
script.src = 'gibberish.js';
// 插入到head标签中
document.head.appendChild(script);

在将script插入到DOM且执行到这段代码之前不会发送请求下载src引入的资源。以这种方式创建的script是异步加载的,相当于添加了async属性。
问题:不是所有浏览器都支持async属性

可将其设置为同步加载

let script = document.createElement('script');
script.src = 'gibberish.js';
// 设置为同步加载
script.async = false;
document.head.appendChild(script);

问题:但是以这种方式获取资源对浏览器预加载器是不可见的,会严重影响它们在资源获取队列中的优先级,可能会严重影响性能。
解决办法:在文档头部显示的声明src引入的资源文件。

<link rel="preload" href="gibberish.js">

XHTML中的变化

在XHTML中使用 JavaScript 必须指定type属性且值为text/javascript,HTML中则可以没有这个属性。
在XHTML中语句a < b中的 < 会被解释成一个标签的开始,又因为作为标签开始的小于号后不能有空格,所以会导致语法错误。
有两种解决办法:

  1. 将代码中所有<换成对应HTML实体形式&lt;
  2. 将代码写在一个CDATA块中,CDATA快表示其内容不作为标签来解析。

在不支持CDATA块的非XHTML兼容浏览器中必须注释CDATA标记,下面这种格式适用于所有线代浏览器。

<script type="text/javascript">
//<![CDATA[
    function fn (a, b) {
      if (a < b) {
        return a - b;
      } else {
        return b - a;
      }
    }
//  ]]
</script>

开发最佳实践

虽然可以直接在HTML文件中嵌入JavaScript代码,但是通常认为最佳实践是尽可能将JavaScript代码放在外部文件。
外部文件的优势:

  1. 可维护性:一个目录中保存所有的JavaScript文件,比分散在HTML中更容易维护。
  2. 缓存:浏览器会根据特定的设置缓存所有的外部连接的JavaScript文件,当其他页面再用到该文件时不用下载,页面加载跟快。
  3. 适应未来:包含外部JavaScript文件的语法在HTML和XHTML中是一样的。

总结

script 标签中 defer 和 async 的区别

  • script :会阻碍 HTML 解析,只有下载好并执行完脚本才会继续解析 HTML。
    在这里插入图片描述

  • async script :解析 HTML 过程中进行脚本的异步下载,下载成功立马执行,有可能会阻断 HTML 的解析。不一定按顺序执行脚本。
    在这里插入图片描述

  • defer script:完全不会阻碍 HTML 的解析,解析完成之后再按照顺序执行脚本。

在这里插入图片描述

  • 动态加载脚本:相当于添加了async属性,但可能会影响属性。

为了提高项目的可维护性,在开发中尽量将javascript代码写在外部文件中再引入使用。
非常感谢这篇文章给予的帮助

我是孤城浪人,一名正在前端路上摸爬滚打的菜鸟,欢迎你的关注。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HTML5 是一种用于构建和呈现网页内容的标准。JS(JavaScript)是一种用于给网页增交互性和动态性的编程语言。在手写 HTML5 和 JavaScript 的过程,我们可以使用纯文本编辑器,如记事本、Sublime Text 等,来编写代码。 首先,我们可以通过 HTML5 语法编写 HTML 结构。在文档的头部,我们使用 `<!DOCTYPE html>` 声明这是一个 HTML5 文档。之后,我们使用 `<html>` 标签来定义整个文档结构。接着,我们在 `<head>` 标签网页的标题、引入 CSS 样式表或 JavaScript 文件等元素。在 `<body>` 标签,我们编写网页的主要内容,例如标题、段落、链接、图像等。 接下来,我们可以利用 JavaScript 来为网页增交互性。我们可以在 `<script>` 标签编写 JavaScript 代码。我们可以使用 JavaScript 提供的函数和方法,处理用户的输入、改变网页的内容、实现动画效果等。 HTML5 和 JavaScript 是紧密联系的。我们可以在 HTML 元素的属性使用 JavaScript,例如通过 `onclick` 属性调用 JavaScript 函数,为按钮添点击事件。我们还可以通过 JavaScript 动态地修改 HTML 元素的内容和样式。 手写 HTML5 和 JavaScript 可以让我们更深入地理解网页的构建和交互原理。通过手动编写代码,我们可以更灵活地控制网页的结构和行为,实现出更好的用户体验。手写代码还可以提高我们的编程能力和调试技巧,使我们更好地理解和利用 HTML5 和 JavaScript 的强大功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值