1_2 HTML中的JavaScript
将JavaScript代码插入到HTML中主要方法是使用<script>标签
<script>标签用于加载脚本与执行脚本
本节重点讲解 浏览器加载脚本的行为
//parser [ 单词 分析器 的意思 ] 在这里指:解析HTML代码的解析器 //fetch [ 单词 取来的意思 ] 在这里指:获取脚本资源 //execution [ 单词 执行的意思 ] 在这里指:执行脚本资源
1)常规加载 [ 不添加 defer延迟属性 或 async 异步属性]
内部执行流程
浏览器正常渲染DOM 遇到script标签 浏览器会中断DOM的渲染 下载并执行脚本 执行完成后 再去渲染剩余的DOM
如果页面中有多个脚本文件 则会按照它们的先后顺序执行 如果脚本之间存在依赖关系 我们将需要将被依赖的文件优先书写
文件位置
通常我们把引入JS脚本的代码写在head头中,浏览器需要加载解释执行完所有的JS脚本后
再来渲染我们的DOM页面。如果当前文档包含的JS脚本比较多的话,会造成浏览器窗口空白时间比较长的问题。
我们推荐是把引入脚本的代码书写在 主内容区之后 /body标签之前。
这样浏览器会先渲染DOM页面 最后再执行JS脚本 用户体验会比较好.
2)延迟加载 [ defer属性 ]
<script defer>
浏览器正常渲染DOM 遇到带defer属性的script标签 浏览器会用异步的方式去下载它 也就是说一边渲染DOM 一边下载JS脚本 等脚本下载完成后 并不执行
而是等整个HTML页面渲染完成后 再去执行脚本.
. 添加了defer属性的脚本在 DOMcontentLoaded事件之前执行
应用场景
引入js的代码写在head中 在脚本代码中操作了dom 浏览器执行到脚本的时候 DOM元素还没有被渲染 导致报错
解决方案1:我们把js代码写在load事件中
解决方案2:我们添加defer属性 页面加载完成后 才执行我们的脚本
3)异步加载
. <script async> [ async 单词 异步的意思 ]
. 异步加载:不需要等待其他脚本,也不会阻塞文档渲染 也就是说 多个JS脚本的加载解释 和 DOM渲染并行的.
. 所以如果存在依赖关系的多个JS脚本 应该避免使用async属性.
. 异步脚本会在页面的load事件前执行 但可能在DOMcontentLoaded事件前或后执行.
应用场景
如果我们脚本并不关心页面中的DOM元素(文档是否解析完毕)
也没有其他脚本依赖需要的数据.
例如:百度统计代码
defer 和 async 的区别
. 相同点:浏览器遇到脚本后 都采用异步的方式下载 DOM树的构建并没有停止
. 不同点:
1. 执行时机的不同
在带defer属性中 异步脚本下载完成后 并不执行 而是等DOM树构建完成显示后再执行
而在带async属性 异步脚本下载后会立即执行 DOM树的构建会中断 等脚本执行完成后 再去构建剩余的DOM树
2. 执行顺序的不同
defer 按照脚本的加载顺序执行
async 先加载完成的脚本先执行 后加载完成的脚本后执行
3. 有依赖关系的脚本 可以使用 defer 而不推荐使用 async
<script type = 'module'> 执行流程 和 defer 一样 <script type="module" async> 执行流程 和 saync 一样
4)设置 发送跨域请求时 是否携带凭据信息 cross origin
4.1)什么是跨域
. 请求地址URL的协议、域名、端口三者之间任意一个 与 当前页面URL不同即为跨域. 详细的可以了解浏览器的同源政策 这里不做展开
. 涉及到跨域的元素有:script[JS加载标签] link css加载标签 img图片加载标签 audio音频加载标签 video视频加载标签
也就是说 上面五个标签都可以设置 cross origin属性
4.2)什么是凭据模式
. 就是告诉浏览器 当前发送的跨域请求 是否携带用户的隐私信息或凭证信息 比如说 Cookie
. 凭据模式主要是用于服务端验证用户的身份,是否携带取决于业务的需求.
4.3)crossorgin属性
// 值1 anonymous 表示不包含凭据 采用匿名模式 [ 单词 匿名的意思 ] // 值2 use-credentials 表示包含凭据 [ 单词 凭据的意思 ] // 不设置这个属性 或者值为空 默认值是 anonymous 不包含凭据
4.4)三种凭据类型
1. Cookie
服务器在响应HTML页面的时候 会给当前的域设置一些Cookie 在同源的情况下 浏览器默认会自动携带Cookie信息
2. tsl证书
在https连接中 发送的tsl客户端证书
3. HTTP身份认证
authorentication [单词 身份认证的意思 ]
// Cross Origin Resource Share 跨域资源共享 // 穿过 源头 资源 共享
5)开启SPI [ 开启子资源完整性验证 ]
5.1)什么是 子资源完整性
它是一个规范:
该规范定义了一种机制,用户代理可通过该机制来验证获取的资源是否已交付而没有意外的操作。
这种完整性验证大大降低了攻击者可以替换恶意内容的风险。
. Sub Resource Integrity 简写 SRI
子 资源 完整性
5.2)inet grity 属性
. inetgrity属性主要用在CDN提供的脚本文件上 作者在上面添加了加密签名(支持sha256 sha384 sha512) inetgrity 属性值就是加密后的签名值.
. 启用SRI后 浏览器会根据资源的签名算法对资源进行验证,如果签名不一致 则不执行资源.
. 如果该资源被篡改,则生成的签名就不一样了 浏览器就不会执行该资源 从而保证了网站的安全性.
. SRI 要求被请求的资源必须同域,或者加 crossorigin 属性,否则 CSS 和 JS 不会起作用。
6)动态加载脚本
因为JavaScript可以使用DOM API
所以通过向DOM中动态添加 script 元素,同样可以加载指定的脚本.
我们只需要创建一个 script 元素并将其添加到DOM中即可.
来看代码示例
var script = document.createElement('script');//1 创建script标签 script.src = '我们想要加载的js文件路径地址'; //2 设置script的src属性 document.head.appendChild(script); //3 追加元素到页面的head中 . 这种方式创建的<script>元素是以异步的方式加载的 相当于添加了 async 属性
. 它存在的问题是:所有的浏览器支持 createElement() 方法 但是 很多浏览器不支持 async 属性
. 我们如果要统一动态脚本的加载行为 我们可以将 异步加载 设置为 同步加载
. 代码在前面的基础上 将async的属性设置为false [script.async = false]
var script = document.createElement('script'); //创建script标签 script.src = 'index.js'; //设置src属性 script.async = false; //把异步加载设置为同步加载 document.head.appendChild(script);//将标签添加到页面上
还需要注意的点
. 以这种方式获取的资源对浏览器预加载是不可见的。
. 这会严重影响它们在 资源获取队列中的优先级。
. 要想让预加载器知道这些动态请求文件的存在 可以在文档头部显式的声明它们
<link rel='preload' href = 'js的路径地址'; [ preload 单词 预加载 的意思]