# Load 事件 vs DOMContentLoaded 事件
> Difference between document load event and document DOMContentLoaded event?
:::info
:star: Load 事件註冊在window物件上,它在網頁「所有」資源載入完畢後才觸發。
:star: DOMContentLoaded 事件在整個document(html)完全讀取和解析後就會被觸發,不需等待網頁資源讀取完成。
(網頁資源:stylesheets, images, subframes等等)
:::
**當打開一個網頁,DOMContentLoaded 和 Load 事件的觸發時機如下:**
> 1. 解析HTML結構。
> 2. 開始加載外部 stylesheets 和 script 。
> 3. 解析並執行 code。
> 4. DOM 樹構建完成。 // :one: DOMContentLoaded 事件被觸發
> 5. 加載完成圖片等外部文件。
> 6. 頁面加載完畢。// :two: Load 事件被觸發
> [color=#f24]
*更詳細的示意圖,可以參考:*

## ex. 在head標籤裡怎麼讀取 script 的內容?
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
document.getElementById('hello').textContent = 'Good Morning!'
</script>
</head>
<body>
<div id="hello"></div>
</body>
</html>
```
:arrow_up: 因為還沒有解析到網頁本體(Document尚未載入),選取不到 DOM
**==解決方法:使用 DOMContentLoaded 事件==**
DOMContentLoaded 事件發生在 document 上。
使用 addEventListener 來捕獲它:
```javascript=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('hello').textContent = 'Good Morning!'
}, false)
</script>
</head>
<body>
<div id="hello"></div>
</body>
</html>
```
## ex. 圖片大小?
``` JavaScript=
<body>
<img id="img" src="https://media.makeameme.org/created/yes-keep-going.jpg">
<script>
function ready() {
alert('DOM is ready');
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
}
document.addEventListener("DOMContentLoaded", ready);
</script>
</body>
```
*image因為還沒有載入,所以圖片大小會是 0x0*
**==使用 load 事件==**
當整個頁面,包括樣式、圖片和其他資源被載入完成時,會觸發 window 上的 load 事件。可以通過 onload 屬性獲取此事件
``` JavaScript=
<img id="img" src="https://media.makeameme.org/created/yes-keep-going.jpg">
<script>
window.addEventListener('load', (event) => {
alert('Page loaded');
// 這時圖片已載入
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
});
</script>
```
就能印出圖片大小
## ex. DOMContentLoaded 和 script
:::warning
當瀏覽器處理一個 HTML 文檔,並在文檔中遇到 script 標籤時,就會在繼續構建 DOM 之前運行它。這是一種防範措施,因為 script 可能想要修改 DOM,甚至對其執行 document.write 操作,所以 DOMContentLoaded 必須等待 script 執行結束。
:::
因此,DOMContentLoaded 肯定在下面的這些 script 執行結束之後發生:
``` JavaScript=
<script>
document.addEventListener("DOMContentLoaded", () => {
alert("DOM ready!");
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"></script>
<script>
alert("Library loaded, inline script executed");
</script>
```
在上面這個例子中,我們首先會看到 “Library loaded…”,然後才會看到 “DOM ready!”(所有script都已經執行結束)。
**例外(暫不討論):**
具有 async 特性(attribute)的 script 不會阻擋 DOMContentLoaded。
使用 document.createElement('script') 動態生成並添加到網頁的 script 也不會阻塞 DOMContentLoaded。
---
更多參考資料
[測試 DOMContentLoaded 和 Load](http://web.archive.org/web/20150405114023/http://ie.microsoft.com/testdrive/HTML5/DOMContentLoaded/Default.html)
[Window: DOMContentLoaded event](https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event)
[Window: load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event)
[页面生命周期:DOMContentLoaded,load,beforeunload,unload](https://zh.javascript.info/onload-ondomcontentloaded)