摘要:所以有可能在所有腳本執(zhí)行完畢后觸發(fā)。如果用戶即將離開(kāi)頁(yè)面或者關(guān)閉窗口時(shí),事件將會(huì)被觸發(fā)以進(jìn)行額外的確認(rèn)。狀態(tài)表示事件即將被觸發(fā)。總結(jié)頁(yè)面事件的生命周期事件在樹(shù)構(gòu)建完畢后被觸發(fā),我們可以在這個(gè)階段使用去訪問(wèn)元素。
頁(yè)面生命周期:DOMContentLoaded, load, beforeunload, unload
原文地址:http://javascript.info/onload...
HTML頁(yè)面的生命周期有以下三個(gè)重要事件:
DOMContentLoaded — 瀏覽器已經(jīng)完全加載了HTML,DOM樹(shù)已經(jīng)構(gòu)建完畢,但是像是 和樣式表等外部資源可能并沒(méi)有下載完畢。
load — 瀏覽器已經(jīng)加載了所有的資源(圖像,樣式表等)。
beforeunload/unload -- 當(dāng)用戶離開(kāi)頁(yè)面的時(shí)候觸發(fā)。
每個(gè)事件都有特定的用途
DOMContentLoaded -- DOM加載完畢,所以js可以訪問(wèn)所有DOM節(jié)點(diǎn),初始化界面。
load -- 附加資源已經(jīng)加載完畢,可以在此事件觸發(fā)時(shí)獲得圖像的大?。ㄈ绻麤](méi)有被在HTML/CSS中指定)
beforeunload/unload -- 用戶正在離開(kāi)頁(yè)面:可以詢問(wèn)用戶是否保存了更改以及是否確定要離開(kāi)頁(yè)面。
來(lái)看一下每個(gè)事件的細(xì)節(jié)。
DOMContentLoadedDOMContentLoaded 由 document 對(duì)象觸發(fā)。
我們使用 addEventListener 來(lái)監(jiān)聽(tīng)它:
document.addEventListener("DOMContentLoaded", ready);
舉個(gè)例子
在這個(gè)例子中 DOMContentLoaded在document加載完成后就被觸發(fā),無(wú)需等待其他資源的載入,所以alert輸出的圖像的大小為0。
這么看來(lái)DOMContentLoaded 似乎很簡(jiǎn)單,DOM樹(shù)構(gòu)建完畢之后就運(yùn)行該事件,不過(guò)其實(shí)存在一些陷阱。
DOMContentLoaded 和腳本當(dāng)瀏覽器在解析HTML頁(yè)面時(shí)遇到了 標(biāo)簽,將無(wú)法繼續(xù)構(gòu)建DOM樹(shù)(譯注:UI渲染線程與JS引擎是互斥的,當(dāng)JS引擎執(zhí)行時(shí)UI線程會(huì)被掛起),必須立即執(zhí)行腳本。所以 DOMContentLoaded 有可能在所有腳本執(zhí)行完畢后觸發(fā)。
外部腳本(帶src的)的加載和解析也會(huì)暫停DOM樹(shù)構(gòu)建,所以 DOMContentLoaded 也會(huì)等待外部腳本。
不過(guò)有兩個(gè)例外是帶async和defer的外部腳本,他們告訴瀏覽器繼續(xù)解析而不需要等待腳本的執(zhí)行,所以用戶可以在腳本加載完成前可以看到頁(yè)面,有較好的用戶體驗(yàn)。
async和defer屬性僅僅對(duì)外部腳本起作用,并且他們?cè)?b>src不存在時(shí)會(huì)被自動(dòng)忽略。
它們都告訴瀏覽器繼續(xù)處理頁(yè)面上的內(nèi)容,而在后臺(tái)加載腳本,然后在腳本加載完畢后再執(zhí)行。所以腳本不會(huì)阻塞DOM樹(shù)的構(gòu)建和頁(yè)面的渲染。
(譯注:其實(shí)這里是不對(duì)的,帶有async和defer的腳本的下載是和HTML的下載與解析是異步的,但是js的執(zhí)行一定是和UI線程是互斥的,像下面這張圖所示,async在下載完畢后的執(zhí)行會(huì)阻塞HTML的解析)
他們有兩處不同:
async | defer | |
---|---|---|
順序 | 帶有async的腳本是優(yōu)先執(zhí)行先加載完的腳本,他們?cè)陧?yè)面中的順序并不影響他們執(zhí)行的順序。 | 帶有defer的腳本按照他們?cè)陧?yè)面中出現(xiàn)的順序依次執(zhí)行。 |
DOMContentLoaded | 帶有async的腳本也許會(huì)在頁(yè)面沒(méi)有完全下載完之前就加載,這種情況會(huì)在腳本很小或本緩存,并且頁(yè)面很大的情況下發(fā)生。 | 帶有defer的腳本會(huì)在頁(yè)面加載和解析完畢后執(zhí)行,剛好在 DOMContentLoaded之前執(zhí)行。 |
所以async用在那些完全不依賴其他腳本的腳本上。
### DOMContentLoaded and styles External style sheets don"t affect DOM, and so `DOMContentLoaded` does not wait for them. 外部樣式表并不會(huì)影響DOM,所以`DOMContentLoaded`并不會(huì)被他們阻塞。 But there"s a pitfall: if we have a script after the style, then that script must wait for the stylesheet to execute: 不過(guò)仍然有一個(gè)陷阱:如果在樣式后面有一個(gè)內(nèi)聯(lián)腳本,那么腳本必須等待樣式先加載完。
發(fā)生這種事的原因是腳本也許會(huì)像上面的例子中所示,去得到一些元素的坐標(biāo)或者基于樣式的屬性。所以他們自然要等到樣式加載完畢才可以執(zhí)行。
DOMContentLoaded需要等待腳本的執(zhí)行,腳本又需要等待樣式的加載。
瀏覽器的自動(dòng)補(bǔ)全Firefox, Chrome和Opera會(huì)在DOMContentLoaded執(zhí)行時(shí)自動(dòng)補(bǔ)全表單。
例如,如果頁(yè)面有登錄的界面,瀏覽器記住了該頁(yè)面的用戶名和密碼,那么在 DOMContentLoaded運(yùn)行的時(shí)候?yàn)g覽器會(huì)試圖自動(dòng)補(bǔ)全表單(如果用戶設(shè)置允許)。
所以如果DOMContentLoaded被一個(gè)需要長(zhǎng)時(shí)間執(zhí)行的腳本阻塞,那么自動(dòng)補(bǔ)全也會(huì)等待。你也許見(jiàn)過(guò)某些網(wǎng)站(如果你的瀏覽器開(kāi)啟了自動(dòng)補(bǔ)全)—— 瀏覽器并不會(huì)立刻補(bǔ)全登錄項(xiàng),而是等到整個(gè)頁(yè)面加載完畢后才填充。這就是因?yàn)樵诘却?b>DOMContentLoaded事件。
使用帶async和defer的腳本的一個(gè)好處就是,他們不會(huì)阻塞DOMContentLoaded和瀏覽器自動(dòng)補(bǔ)全。(譯注:其實(shí)執(zhí)行還是會(huì)阻塞的)
window.onloadwindow對(duì)象上的onload事件在所有文件包括樣式表,圖片和其他資源下載完畢后觸發(fā)。
下面的例子正確檢測(cè)了圖片的大小,因?yàn)?b>window.onload會(huì)等待所有圖片的加載。
window.onunload
用戶離開(kāi)頁(yè)面的時(shí)候,window對(duì)象上的unload事件會(huì)被觸發(fā),我們可以做一些不存在延遲的事情,比如關(guān)閉彈出的窗口,可是我們無(wú)法阻止用戶轉(zhuǎn)移到另一個(gè)頁(yè)面上。
所以我們需要使用另一個(gè)事件 — onbeforeunload。
window.onbeforeunload如果用戶即將離開(kāi)頁(yè)面或者關(guān)閉窗口時(shí),beforeunload事件將會(huì)被觸發(fā)以進(jìn)行額外的確認(rèn)。
瀏覽器將顯示返回的字符串,舉個(gè)例子:
window.onbeforeunload = function() { return "There are unsaved changes. Leave now?"; };
有些瀏覽器像Chrome和火狐會(huì)忽略返回的字符串取而代之顯示瀏覽器自身的文本,這是為了安全考慮,來(lái)保證用戶不受到錯(cuò)誤信息的誤導(dǎo)。
readyState如果我們?cè)谡麄€(gè)頁(yè)面加載完畢后設(shè)置DOMContentLoaded會(huì)發(fā)生什么呢?
啥也沒(méi)有,DOMContentLoaded不會(huì)被觸發(fā)。
有一些情況我們無(wú)法確定頁(yè)面上是否已經(jīng)加載完畢,比如一個(gè)帶有async的外部腳本的加載和執(zhí)行是異步的(注:執(zhí)行并不是異步的-_-)。在不同的網(wǎng)絡(luò)狀況下,腳本有可能是在頁(yè)面加載完畢后執(zhí)行也有可能是在頁(yè)面加載完畢前執(zhí)行,我們無(wú)法確定。所以我們需要知道頁(yè)面加載的狀況。
document.readyState屬性給了我們加載的信息,有三個(gè)可能的值:
loading 加載 - document仍在加載。
interactive 互動(dòng) - 文檔已經(jīng)完成加載,文檔已被解析,但是諸如圖像,樣式表和框架之類的子資源仍在加載。
complete - 文檔和所有子資源已完成加載。狀態(tài)表示 load 事件即將被觸發(fā)。
所以我們可以檢查 document.readyState 的狀態(tài),如果沒(méi)有就緒可以選擇掛載事件,如果已經(jīng)就緒了就可以直接立即執(zhí)行。
像這樣:
function work() { /*...*/ } if (document.readyState == "loading") { document.addEventListener("DOMContentLoaded", work); } else { work(); }
每當(dāng)文檔的加載狀態(tài)改變的時(shí)候就有一個(gè)readystatechange事件被觸發(fā),所以我們可以打印所有的狀態(tài)。
// current state console.log(document.readyState); // print state changes document.addEventListener("readystatechange", () => console.log(document.readyState));
readystatechange 是追蹤頁(yè)面加載的一個(gè)可選的方法,很早之前就已經(jīng)出現(xiàn)了。不過(guò)現(xiàn)在很少被使用了,為了保持完整性還是介紹一下它。
readystatechange的在各個(gè)事件中的執(zhí)行順序又是如何呢?
輸出如下:
[1] initial readyState:loading
[2] readyState:interactive
[2] DOMContentLoaded
[3] iframe onload
[4] readyState:complete
[4] img onload
[4] window onload
方括號(hào)中的數(shù)字表示他們發(fā)生的時(shí)間,真實(shí)的發(fā)生時(shí)間會(huì)更晚一點(diǎn),不過(guò)相同數(shù)字的時(shí)間可以認(rèn)為是在同一時(shí)刻被按順序觸發(fā)(誤差在幾毫秒之內(nèi))
document.readyState 在 DOMContentLoaded前一刻變?yōu)?b>interactive,這兩個(gè)事件可以認(rèn)為是同時(shí)發(fā)生。
document.readyState 在所有資源加載完畢后(包括iframe和img)變成complete,我們可以看到complete、 img.onload和window.onload幾乎同時(shí)發(fā)生,區(qū)別就是window.onload在所有其他的load事件之后執(zhí)行。
總結(jié)頁(yè)面事件的生命周期:
DOMContentLoaded事件在DOM樹(shù)構(gòu)建完畢后被觸發(fā),我們可以在這個(gè)階段使用js去訪問(wèn)元素。
async和defer的腳本可能還沒(méi)有執(zhí)行。
圖片及其他資源文件可能還在下載中。
load事件在頁(yè)面所有資源被加載完畢后觸發(fā),通常我們不會(huì)用到這個(gè)事件,因?yàn)槲覀儾恍枰饶敲淳谩?/p>
beforeunload在用戶即將離開(kāi)頁(yè)面時(shí)觸發(fā),它返回一個(gè)字符串,瀏覽器會(huì)向用戶展示并詢問(wèn)這個(gè)字符串以確定是否離開(kāi)。
unload在用戶已經(jīng)離開(kāi)時(shí)觸發(fā),我們?cè)谶@個(gè)階段僅可以做一些沒(méi)有延遲的操作,由于種種限制,很少被使用。
document.readyState表征頁(yè)面的加載狀態(tài),可以在readystatechange中追蹤頁(yè)面的變化狀態(tài):
loading — 頁(yè)面正在加載中。
interactive -- 頁(yè)面解析完畢,時(shí)間上和 DOMContentLoaded同時(shí)發(fā)生,不過(guò)順序在它之前。
complete -- 頁(yè)面上的資源都已加載完畢,時(shí)間上和window.onload同時(shí)發(fā)生,不過(guò)順序在他之前。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/88920.html
摘要:所以有可能在所有腳本執(zhí)行完畢后觸發(fā)。如果用戶即將離開(kāi)頁(yè)面或者關(guān)閉窗口時(shí),事件將會(huì)被觸發(fā)以進(jìn)行額外的確認(rèn)。狀態(tài)表示事件即將被觸發(fā)??偨Y(jié)頁(yè)面事件的生命周期事件在樹(shù)構(gòu)建完畢后被觸發(fā),我們可以在這個(gè)階段使用去訪問(wèn)元素。 頁(yè)面生命周期:DOMContentLoaded, load, beforeunload, unload 原文地址:http://javascript.info/onload.....
摘要:簡(jiǎn)言理解頁(yè)面的生命周期,文檔加載事件及順序?qū)﹂_(kāi)發(fā)有十分的重要意義。同步的腳本最先執(zhí)行,它先于事件執(zhí)行。當(dāng)準(zhǔn)備就緒時(shí),事件在上觸發(fā)。表示文檔的當(dāng)前狀態(tài),可以在事件中跟蹤文檔狀態(tài)的變更。已經(jīng)解析完畢時(shí)觸發(fā),幾乎與同時(shí)發(fā)生,但在事件之前觸發(fā)。 簡(jiǎn)言 理解WEB頁(yè)面的生命周期,文檔加載事件及順序?qū)EB開(kāi)發(fā)有十分的重要意義。如果不理解,在元素未加載就提前操作元素,則得不到想要的結(jié)果。而如果頁(yè)面...
摘要:所以所需要的時(shí)間必然大于等于所需要的時(shí)間。頁(yè)面的生命周期主要有三個(gè)重要的事件,已經(jīng)構(gòu)建好,可以對(duì)節(jié)點(diǎn)進(jìn)行操作,所有資源加載完畢,可以對(duì)資源進(jìn)行一系列操作,比如獲取圖片寬高等基本不會(huì)用到,當(dāng)瀏覽器窗口關(guān)閉或者刷新時(shí),會(huì)觸發(fā)事件。 DOMContentLoaded與load的區(qū)別 showImg(https://segmentfault.com/img/remote/14600000192...
摘要:坑無(wú)視和是十分特殊的事件,要求事件處理函數(shù)內(nèi)部不能阻塞當(dāng)前線程,而卻恰恰就會(huì)阻塞當(dāng)前線程,因此規(guī)范中以明確在和中直接無(wú)視這幾個(gè)方法的調(diào)用。 前言 ?最近實(shí)施的同事報(bào)障,說(shuō)用戶審批流程后直接關(guān)閉瀏覽器,操作十余次后系統(tǒng)就報(bào)用戶會(huì)話數(shù)超過(guò)上限,咨詢4A同事后得知登陸后需要顯式調(diào)用登出API才能清理4A端,否則必然會(huì)超出會(huì)話上限。?即使在頁(yè)面上增添一個(gè)登出按鈕也無(wú)法保證用戶不會(huì)直接關(guān)掉瀏覽器...
閱讀 1588·2021-09-26 09:46
閱讀 2675·2021-09-07 09:59
閱讀 2760·2021-09-07 09:59
閱讀 1887·2019-08-30 14:20
閱讀 936·2019-08-26 13:39
閱讀 3184·2019-08-26 12:24
閱讀 781·2019-08-26 11:55
閱讀 1222·2019-08-23 16:49