使用<script>元素将 JavaScript 插入 HTML是给页面添加灵魂的最直接方式。这个元素是由网景公司创造被加入到 HTML 规范,网景对于前端想个什么词来形容呢,混沌初开,开山鼻祖,女娲造人…<script>元素目前规定了8 个属性。我们按照添加方式或者加载执行顺序不同逐个了解
添加方式
- 行内脚本
直接把代码放在<script>元素中就行,从上到下解释执行,阻塞页面的渲染,另外如果执行的代码中有关键字字符串</script> 标签,需要使用\转移
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>你好</title>
</head>
<body>
你好
<script>
console.log('打印');
console.log("<\/script>");
</script>
加油!
</body>
</html>
- 外部脚本
也是我们在开发实践过程中最常用的添加方式,很简单,使用 src 属性 添加一个URL值指向JavaScript 文件即可
<script src="hello.js"></script>
在不考虑其他属性的情况下,在解释外部 JavaScript 文件时,页面也会阻塞。
我们也可以添加一个其他网站的js
<script src="http://别人家的域名/hello.js"></script>
你在自己的家里放了别人的一部智能设备,是不是要特别注意一下了,这个智能设备的远程程序是不是被修改过,所以integrity 属性 就是用来判断这个 js 有没有被修改过,它的值是使用某些算法得出的文件摘要是个哈希值,文件被改动哈希值会变。利用这个特点,integrity 的值可以是多个,使用空格分开,要加载的文件的哈希值只要匹配其中任意一个算通过,否则浏览器不予解释,部分浏览器支持。
- 动态添加
let script = document.createElement('script');
script.src = 'gibberish.js';
script.async = false;
document.head.appendChild(script)
加载顺序 和 执行顺序
js 的执行顺序通常是自上而下按照先后顺序加载解释并执行的,所以行内添加的方式没得商量解释执行就完了,所以我们主要想一下外部脚本的方式是怎么加载的,在只有src属性的情况下 ,HTML 在遇到 script 元素的时候就开始加载,所以把大量的script 一起放到头部会导致阻塞页面的渲染,一般会放到body 底部,这样不会影响页面的渲染
<!DOCTYPE html>
<html>
<head>
<title>你好</title>
</head>
<body>
<!-- 这里是页面内容 -->
<script src="hello1.js"></script>
<script src="hello2.js"></script>
</body>
</html>
defer 属性 和 async 属性
<script defer src="hello1.js"></script>
<script async src="hello2.js"></script>
浏览器遇到 defer 虽然会立即下载,但会推迟执行,推迟到整个页面解释完毕后再执行
浏览器遇到 async 也会立即下载,但不确定执行时间,这个执行时间保证页面的load事件执行之前,说到load事件,我们先大概了解一下页面的加载步骤以及会触发的事件
大致步骤
- 解析HTML文档结构
- 加载外部样式及JavaScript
- 解析执行JavaScript
- DOM树渲染完成
- 加载未完成的资源
- 页面加载成功
触发的事件
- document的onreadystatechange
- document的DOMContentLoader
- window 的load
示例
document.onreadystatechange = function(){ //文档加载状态改变事件处理,只要改变就触发,所以是多次执行
if(document.readyState === 'loading'){ //document 加载中
console.log(document.readyState);
}
if(document.readyState === 'interactive'){
//互动文档加载完成,文档解析完成但是图片、样式表、框架等子资源还再加载
console.log(document.readyState);
}
if(document.readyState === 'complete'){
//文档和所有子资源加载完成 window 的load事件即将被触发
}
}
document.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM加载完毕');
});
window.onload = function(){
console.log('都好了,燥起来')
}
动态加载对于浏览器解析不可见,只有再运行的时候才动态创建了 script元素,然后加载解释执行,这种无法让浏览器判断优先级,如果想让浏览器按照预期的加载顺序加载,可以再头部显示声明
<link rel="preload" href="hello.js">
关于跨源
浏览器安全中有一项同源策略,简单点协议+域名+端口,三者任意不一样都算跨源,但是<audio>、<img>、<link>、<script> 和 <video> 均有一个跨域属性 (crossOrigin property),允许你请求别人家的资源,直接 src 指向就可以了,但是我们自己站点的cookie 是不可能随便给这个“别人家的js” 的请求的,我们还知道cookie 在ajax请求的时候是会被带上的,那么 crossorigin 属性就是会把这种链接请求转变成 ajax请求,所以这时候我们需要设置 crossorigin ,它的值crossorigin=
"anonymous"配置文件请求不必设置凭据标志。crossorigin="use-credentials"设置凭据
标志,意味着出站请求会包含凭据。同时“别人家的服务器” 允许你这样访问(设置了allow-control-allow-origin) 所以crossorigin 的使用同时需要满足
- 对方允许
- 当心设置,要不要把关键信息给对方
很好理解,这种方式还可以捕获到对方的js 具体错误,所以知道详细错误肯定需要对方授权,把 自己的凭证给对方也当然要小心
小结
8个属性
- src
- integrity
- async
- defer
- crossorigin
- charset
- language
- type
前5个要掌握,后三个忽略
最后欣赏个名句
吾尝跂而望矣,不如登高之博见也。
摘自《荀子·劝学》
解释:我曾经踮起脚向远处望,(却)不如登到高处见得广。