乐趣区

JS完美收官之js加载时间线

什么是 js 加载时间线?

浏览器在开始运行一个页面的时候,首先它会初始化 js 功能,当 js 发挥它的功能时候,记录了一系列浏览器按照顺序做的事情,也就是一个执行顺序,谁在谁之前发生,谁在谁之后发生。

js 时间线主要步骤:[创建 document 对象开始——> 文档解析完——> 文档加载完并执行完]

1. 创建 Document 对象,开始解析 web 页面。这个阶段 document.readyState = ‘loading’.

代码验证:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js 加载时间线测试 </title>
</head>
<body>
    <script type="text/javascript">
        console.log(document.readyState);      
</script>
</body>
</html>

执行结果:

2.遇到 link 外部 css,创建线程,进行异步加载,并继续解析文档。

3.遇到 script 外部 js,并且没有设置 async、defer,浏览器同步加载,并阻塞,等待 js 加载完成并执行该脚本,然后继续解析文档。

4.遇到 script 外部 js,并且设置有 async、defer,浏览器创建线程异步加载,并继续解析文档。(异步禁止使用 document.write())

⚠️ 注意:**async 属性的脚本,脚本加载完成后立即执行。defer 属性脚本要等到 dom 解析完成后再执行。

⚠️ 注意:(异步禁止使用 document.write(),因为当你整个文档解析到差不多,再调用 document.write(),会把之前所有的文档流都清空,用它里面的文档代替,除了异步禁止,而且当内容全部加载完毕后也要禁止使用 document.write(),也就是 window.onload,document.write 任何情况下都不要用,其实也没啥用)

代码验证:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js 加载时间线测试 </title>
</head>
<body>
    <div style="width: 100px;height: 100px;background-color: red;"></div>
    <script type="text/javascript">
        document.write('hello world')   
</script>
</body>
</html>

执行结果:

在 window.onload 后再次验证

代码验证:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js 加载时间线测试 </title>
</head>
<body>
    <div style="width: 100px;height: 100px;background-color: red;"></div>
    <script type="text/javascript">
    window.onload = function(){document.write('hello world')   
    }      
</script>
</body>
</html>

执行结果:

5.遇到 img 等(带有 src),先正常解析 dom 结构,然后浏览器异步加载 src,并继续解析文档。看到标签直接生产 dom 树,不用等着 img 加载完 scr。

6.当文档解析完成(domTree 建立完毕,不是加载完毕,解析在加载之前),document.readyState = ‘interactive’。

代码验证:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js 加载时间线测试 </title>
</head>

<body>
    <script type="text/javascript">
        //document 创建时候的状态
        console.log(document.readyState);
        // 当 dom 解析完成后的状态(dom 树建立完成后)document.onreadystatechange = function () {console.log(document.readyState);
        }
</script>
</body>

</html>

执行结果:

7.文档解析完成后,所有设置有 defer 的脚本会按照顺序执行。(注意与 async 的不同, 但同样禁止使用 document.write());

8. 文档解析完成后,document 对象触发 DOMContentLoaded 事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段。

代码验证:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>js 加载时间线测试 </title>
</head>

<body>
    <script type="text/javascript">
        //document 创建时候的状态
        console.log(document.readyState);
        // 当 dom 解析完成后的状态(dom 树建立完成后)document.onreadystatechange = function () {console.log(document.readyState);
        }
         // 这里要注意 DOMContentLoaded 比较特殊,必须绑定在 addEventListener 上好使
        document.addEventListener('DOMContentLoaded',function(){console.log('来呀!快活呀!');
            
        },false)
</script>
</body>

</html>

执行结果:

⚠️ 注意:** 我们要注意的是 DOMContentLoaded 事件比较特殊,它必须绑定在 addEventListener 上好使,用 onDOMContentLoaded 绑定没用.

在 jquery 中有一个 $(document).ready(function(){}) 方法,这个方法就是当 dom 解析完就执行的部分。

// 当 dom 解析完就执行的部分
$(document).ready(function(){// 这里面写着主函数体})

这个 ready 方法经常会在面试中问到,ready 和 window.onload 的区别?

区别:区别就是 ready 方法快,window.onload 慢,因为 ready 是 dom 解析完就执行,而 window.onload 则是加载完再执行。ready 方法的底层原理就是依据 document.readyState 变成 interactiveDOMContentLoaded 事件

9.当所有 async 的脚本加载完成并执行后、img 等加载完成后(页面所有的都执行加载完之后),document.readyState = ‘complete’,window 对象触发 load 事件。

10.从此,以异步响应方式处理用户输入、网络事件等。

『好啦,以上呢就给大家的分享啦,欢迎大家留言,谢谢支持~』

退出移动版