前端的纯技术就是对规范的认知
什么是domcontentloadede
首先想到的是查看w3c的html5规范、domcontentloaded事件在什么时候触发:
ユーザーエージェントがドキュメントの解析を停止したら、ユーザーエージェントは次の手順を実行する必要があります。
1.現在のドキュメントの準備を「インタラクティブ」に設定し、挿入ポイントを未定義にします。
オープン要素のスタックからすべてのノードをポップします。
2.ドキュメントが完了したときに実行されるスクリプトのリストが空でない場合は、これらのSubstepsを実行します。
2.1イベントループをスピンして、ドキュメントが完了したときに実行されるスクリプトのリストの最初のスクリプトが「パーサーが解釈する準備ができている」フラグセットがあり、パーサーのドキュメントにはスクリプトをブロックしているスタイルシートがありません。
2.2ドキュメントが解析が終了したときに実行されるスクリプトのリストで最初のスクリプトを実行します。
2.3ドキュメントの解析が終了したときに実行されるスクリプトのリストから最初のスクリプト要素を削除します(つまり、リストの最初のエントリをシフトします)。
2.4ドキュメントが完了したときに実行されるスクリプトのリストがまだ空でない場合は、これらのsubsepsをsubrepep 1から再び繰り返します。
3.ドキュメントにdomcontentloadedがbubblesという名前の単純なイベントを発射するタスクをキューにします。
规范总是那么的晦涩、但至少有一点是可以明确了的、就是在js
接下来看看MDNdomcontentLoaded事件的文档:
スタイルシート、画像、サブフレームがロードを終了するのを待つことなく、ドキュメントが完全にロードされて解析されたときに、domcontentloadedイベントが起動されます
注:Stylesheetロードブロックスクリプトの実行をロードするため、
<link rel="stylesheet" ...>の後に<script>がある場合、ページは解析が終了せず、スタイルシートがロードされるまでdomcontentloadedは発射されません。
这么看来、至少可以得出这么一个理论:domcontentLoaded
它的触发时机是:加载完页面、解析完所有标签(不interactive执行 css
而js的执行、需要等待位于它前面的css 加载(如果是外联的话)、执行完成、因为js可能会依赖位于它前面的css计算出来的样式。
实践是检验真理的唯一标准
实验1:domcontentloaded事件不直接等待CSS文件、图片的加载完成
index.html:
<!doctype html> <html lang = "zh-cn"> <head> <meta charset = "utf-8"> <title> </title> <link rel = "styleSheet" type = "text/css" href = "./ css/main.css" rel = "external nofollow"> <p> <img src = "./ img/chrome-girl.jpg"> </body> </html>
图一
如果页面中没有スクリプト标签、domcontentloaded事件并没有等待CSS文件、图片加载完成。
クロム开发者工具的タイムライン面板可以帮我们记录下浏览器的一举一动。图一中红色小方框中的蓝线、表示ドムコンテンテントロード
实验2:domcontentloaded事件需要等待js执行完才触发
index.html:
<!doctype html> <html lang = "zh-cn"> <head> <meta charset = "utf-8"> <title> </title> <script type = "text/javascript"> console.timestamp( 'ヘッドのリンクの前にインラインスクリプト'); window.addeventlistener( 'domcontentloaded'、function(){console.timestamp( 'domcontentloaded event');}); </script> <link rel = "styleSheet" type = "text/css" href = "./ css/main.css" rel = "returation nofollow" rel = "external nofollow"> <スクリプトタイプ= "text/javascript"> console.timestamp( 'inline inling in head'); </script> </head> <body> <p> content </p> <img src = "./ img/chrome-girl.jpg"> <script type = "text/javascript" src = "./ js/main.js"> </script> </body> </html>main.js:
console.timestamp( 'ボディのリンク後の外部スクリプト');
图二
如果页面中静态的写有スクリプト标签、domcontentloaded
而スクリプト标签中的js需要等待位于其前面的css的加载完成。
console.timestamp()可以向タイムライン中添加一条记录、并对应上方的一条黄线。
从图二中可以看出、在、CSS之前的JS、而在CSS之后的JS、需要等待CSS加载完后才执行、Main.js早就加载完了、但还是要等main.css
图三
现代浏览器会并发的预加载CSS、JS、也就是一开始就并发的请求这些资源、但是、执行CSS
实验3:IMG 何时开始解码、绘制?
从图三中我们可以发现一个有趣的地方:img、但延迟了一段时间才开始解码。如图二、图三中的红框所示、截图中只框出了一部分表示解码的记录、而实际上这些表示解码的记录一直持续到、img、如图四所示、如图四所示、img是一边加载一边解码的:
图三
现代浏览器会并发的预加载CSS、JS、也就是一开始就并发的请求这些资源、但是、执行CSS
实验3:IMG 何时开始解码、绘制?
从图三中我们可以发现一个有趣的地方:img、但延迟了一段时间才开始解码。如图二、图三中的红框所示、截图中只框出了一部分表示解码的记录、而实际上这些表示解码的记录一直持续到、img、如图四所示、如图四所示、img是一边加载一边解码的:
图四
抱着“猜想 - - 验证”的想法、我猜想这是因为img这个资源是否需要展现出来、需要等所有的js和css的执行完才知道、因为main.js dom操作、比如删除这个img元素、或者修改其src属性、而css可能会将其display: none
图五
图六
图七
後JS和CSS、IMG的数据一接收到就马上开始解码了。
图六中没有js、但img要等到CSS加载完才开始解码。
图七的代码跟图六的代码唯display: none; 、这使得img虽然请求了、但根本没有进行解码。
这说明、img 是否需要解码、绘图(ペイント)出来、确实需要等css 加载、执行完才能知道。也就是说、css
图八
图八对应的代码:
<!doctype html> <html lang = "zh-cn"> <head> <meta charset = "utf-8"> <title> </title> <script type = "text/javascript"> console.timestamp( 'inline script in'); window.addeventlistener( 'domcontentloaded'、function(){console.timestamp( 'domcontentloaded event');}); </script> </head> <body> <p> content </p> <img src = "./ img/chrome-girl.jpg"> <script type = "text/javascript" src = "./ js/main.js"> </script> </body> </html>非常令人惊讶、在有、Js而没有css的页面中、img 居然能够在收到数据后就立刻开始解码、绘图( paint)、也就是说、js并没有阻塞img
我们常用的jQuery的$(document).ready()方法、就是对domcontentloaded 事件的监听(当然、其内部还会通过模拟domcontentloaded事件和监听domcontentloaded
减小CSS文件体积、把单个CSS文件分成几个文件以并行加载、减少CSS对JS的阻塞时间
次要的js文件、通过动态插入スクリプト标签来加载(动态插入的スクリプト标签不阻塞domcontentloaded 事件的触发)
css中使用的精灵图、可以利用对img的预加载、放在html中跟css文件一起加载
在做实验的过程中、感觉、クロム开发者工具的、タイムライン、面板非常强大、浏览器的一举一动都记录下来。以前我们前端开发要想理解、探索浏览器的内部行为、或者摸着石头过河的做黑盒测试、或者事倍功半的研究浏览器源码、唯一高效点的做法就是学习别人的研究经验、看老外的文章、但浏览器的发展日新月异(比如这次实验发现的、但浏览器的发展日新月异(比如这次实验发现的、不阻塞、别人的经验始终不是最新、最适合的、别人的经验始终不是最新、最适合的、关键是要结合自己的业务、需求场景、有针对性的做分析和优化。、有针对性的做分析和优化。
詩
以上测试环境为windows/chrome、并用fiddler模拟慢速网络