DOMContentLoaded事件

DOMContentLoaded也就是jquery党常用的ready事件,一般在dom ready之后才会进行一些dom操作,事件绑定等。

定义

定义可以看w3c的规范

Once the user agent stops parsing the document, the user agent must run the following steps:

  • 1. Set the current document readiness to “interactive” and the insertion point to undefined.
  • Pop all the nodes off the stack of open elements.
  • 2. If the list of scripts that will execute when the document has finished parsing is not empty, run these substeps:
  • 2.1 Spin the event loop until the first script in the list of scripts that will execute when the document has finished parsing has its “ready to be parser-executed” flag set and the parser’s Document has no style sheet that is blocking scripts.
  • 2.2 Execute the first script in the list of scripts that will execute when the document has finished parsing.
  • 2.3 Remove the first script element from the list of scripts that will execute when the document has finished parsing (i.e. shift out the first entry in the list).
  • 2.4 If the list of scripts that will execute when the document has finished parsing is still not empty, repeat these substeps again from substep 1.
  • 3. Queue a task to fire a simple event that bubbles named DOMContentLoaded at the Document.

看着略有些晕,大概意思是js执行完之后才会触发DOMContentLoaded事件。

再看MDN里的解释

The DOMContentLoaded event is fired when the document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading (the load event can be used to detect a fully-loaded page).

Note: Stylesheet loads block script execution, so if you have a <script> after a <link rel="stylesheet" ...>, the page will not finish parsing – and DOMContentLoaded will not fire – until the stylesheet is loaded.

 

这么看DOMContentLoaded不会等待css,图片加载完,但是如果在css文件后面有js文件,那DOMContentLoaded事件会等css加载完之后触发。

原因是js的执行需要等待位于它前面的css加载执行完,因为js可能依赖css里的一些样式。

那么我们来测试一下

测试验证

1、页面里只有css和img

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
    <p>Content</p>
    <img src="images/1.png">
</body>
</html>

Timeline里结果如下

蓝色的那条粗线代表DOMContentLoaded,可以看到 DOMContentLoaded没有等待css和img加载

 

2、页面里只有js和img

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <p>Content</p>
    <img src="images/1.png">
    <script type="text/javascript" src="2.js"></script>
</body>
</html>

可以看到确实是在执行了js之后,才触发DOMContentLoaded

 

3、再看下js和css同时存在的情况

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
    <p>Content</p>
    <img src="images/1.png">
    <script type="text/javascript" src="2.js"></script>
</body>
</html>

 

可以看到先等css加载完,之后js才开始执行,js执行完之后才触发DOMContentLoaded

 

通过上面三个实验,对于js和css对DOMContentLoaded的影响也清楚了。

那么还有一个问题,如果是动态插入的js呢

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
    <p>Content</p>
    <img src="images/1.png">
    <script type="text/javascript">
   	var script=document.createElement('script');
   	script.setAttribute('type','text/javascript');
   	script.setAttribute('src','2.js');
   	document.getElementsByTagName('body')[0].appendChild(script);
    </script>
</body>
</html>

 

可以看到2.js的加载和执行对DOMContentLoaded无影响

结论

更早的触发DOMContengLoaded事件,可以使页面更早的可交互,所以对于次要的js文件,可以采用动态加载的方式