document对象中有个write()方法可以用于往页面写入内容。

  1. document.write("替换内容!");
  2. document.write("<p>这是p标签</p>"); // 浏览器会把p标签解析

目前,document.write()有两个现象:
1、直接在文档后面追加内容

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <h1>这是H1</h1>
  11. <p>这是H1</p>
  12. </body>
  13. </html>
  14. <script>
  15. document.write("替换");
  16. </script>

image.png
💡 这是因为script也属于标签,故也会被renderTree进行渲染,当renderTree渲染的时候遇到document.write(),由于页面还没有渲染完成,所以无法写入只能在文档后面进行追加。

2、将body里的内容全部替换,重写整个文档

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <h1>这是H1</h1>
  11. <p>这是H1</p>
  12. </body>
  13. </html>
  14. <script>
  15. window.onload = function () {
  16. document.write("替换");
  17. };
  18. </script>

image.png
💡 window.onloadrenderTree渲染完成且资源(如img)全部加载完成后才会触发该事件,这个时候document.write()就会把body内全部内容重写

这个时候就要引出「时间线」的概念啦。

时间线

:::info 浏览器开始加载页面的那一刻开始,到页面加载完毕,整个过程中按顺序发生的每件事情就叫时间线。 ::: 时间线、解析与渲染 - 图3

📌 script 标签 defer 和 async 属性的区别: defer只加载js脚本但是只在文档加载完毕后执行 async加载js脚步后立即执行(不能确定执行顺序)

所以这两个属性适用没有DOM依赖和没有先后执行顺序要求的时候。

DOMContentLoadedload事件

可以看到在「时间线」中会触发两个事件:DOMContentLoadedload
**DOMContentLoaded**等文档解析完成后触发,我们可以在该事件内判断文档解析的状态,该事件没有具柄的写法(例如**onclick****onload**):

  1. console.log(document.readyState);
  2. document.addEventListener("DOMContentLoaded",function(){
  3. console.log(document.readyState);
  4. },flase)
  5. // loading
  6. // interactive
  7. // complete

load事件等文档解析完成+资源加载完成后才会触发(浪费时间):

该事件也可以用在img标签上,表示img加载完成后触发!!!

  1. window.onload = function(){
  2. //...
  3. }