本文轉(zhuǎn)載自:眾成翻譯
譯者:阿杜(本人)—HappyAdu
鏈接:http://www.zcfy.cc/article/1479
原文:https://www.sitepoint.com/jquery-document-ready-plain-javascript/
在jQuery中ready
方法在DOM完全下載后立即執(zhí)行其中的代碼。因?yàn)樗堑人械腄OM元素都加載完畢顷编,才執(zhí)行給定的函數(shù),所以你能確定那些試圖操作和訪問(wèn)元素節(jié)點(diǎn)的方法都能被執(zhí)行碍粥。
在jQuery 3.0的版本前, ready
經(jīng)典用法是用一個(gè)匿名函數(shù),像這樣:
$(document).ready(function() {
// Handler for .ready() called.
});
jQuery 3.0 ready() 變化
在jQuery 3.0發(fā)布之前瘟裸,有以下幾種方法稱之為ready
方法:
在document元素上操作:
$(document).ready(handler);
在空元素上操作:
$().ready(handler);
或者直接(即不在一個(gè)具體的元素上)操作:
$(handler);
上述所有命名的變種在功能上是等價(jià)的。無(wú)論是哪個(gè)元素乃戈,在DOM加載完畢之后其指定的處理程序都將會(huì)被調(diào)用。換句話說(shuō)亩进,這里的DOM加載完畢并不表示在文檔中的某個(gè)具體的元素症虑,比如img元素,加載完畢归薛。相反侦讨,這里表示的是整個(gè)DOM樹(shù)加載完畢。
在jQuery 3.0中,除了$(handler)
其他的ready方法都被棄用苟翻。官方聲明為此:
這是因?yàn)檫x擇器并沒(méi)有和
ready()
建立聯(lián)系伯病,不僅低效而且會(huì)導(dǎo)致瀏覽器引擎對(duì)該方法的行為進(jìn)行不正確的假設(shè)发侵。
ready
事件和 load
事件的區(qū)別
當(dāng)DOM加載完畢且元素能夠被安全訪問(wèn)時(shí)就會(huì)觸發(fā)ready
事件。另一方面匾委,load
事件卻在DOM和所有資源加載后觸發(fā)需忿。
可以像下面這樣使用load
事件:
$(window).on("load", function(){
// Handler when all assets (including images) are loaded
});
這樣的話诅炉,不僅僅要等到DOM結(jié)構(gòu)能完全訪問(wèn),而且還需要等到所有的圖片資源完全加載完畢(加載時(shí)間取決于圖片文件大形堇濉)才能執(zhí)行函數(shù)涕烧。
正常的DOM操作你可能不需要load
事件,但是如果你想要在所有的資源被加載完畢之前展示一個(gè)旋轉(zhuǎn)的加載器樣式,比如汗洒,又或者你想要用JS計(jì)算一下圖片的大小议纯,這可能是一個(gè)好的選擇。
你可能不需要jQuery.ready()
ready
方法可以確保代碼只在所有DOM元素能被安全操縱時(shí)才執(zhí)行溢谤。 但這意味著什么呢瞻凤?這意味著當(dāng)你要執(zhí)行的js代碼嵌在HTML中某個(gè)片段中時(shí),瀏覽器也要加載完以下元素才能執(zhí)行世杀。就像下面這個(gè)例子一樣:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>.ready() tutorial</title>
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script>
$(function(){ // .ready() callback, is only executed when the DOM is fully loaded
var length = $("p").length;
// The following will log 1 to the console, as the paragraph exists.
// This is the evidence that this method is only called when the
// DOM is fully loaded
console.log(length);
});
</script>
</head>
<body>
<p>I'm the content of this website</p>
</body>
</html>
如果你要執(zhí)行的javascript代碼放在body末尾阀参,你就可能不需要使用ready()
方法,因?yàn)闉g覽器解析到j(luò)avascript時(shí)你可能試圖操縱和訪問(wèn)的DOM元素已經(jīng)被加載完了:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>.ready() tutorial</title>
</head>
<body>
<p>I'm the content of this website</p>
<script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script>
var length = $("p").length;
// The following will log 1 to the console, as the paragraph exists.
console.log(length);
</script>
</body>
</html>
原生JavaScript ready()替代
對(duì)于現(xiàn)代瀏覽器以及IE9+瞻坝,你可以通過(guò)監(jiān)聽(tīng) DOMContentLoaded
事件實(shí)現(xiàn)ready()
相同的功能:
document.addEventListener("DOMContentLoaded", function(){
// Handler when the DOM is fully loaded
});
但是蛛壳,請(qǐng)注意,如果事件已經(jīng)發(fā)射所刀,回調(diào)將不會(huì)被執(zhí)行衙荐。為了確保回調(diào)總是運(yùn)行浮创,jQuery檢查文檔(reference) 的“readyState”屬性赫模,如果屬性值變?yōu)?complete
,則立即執(zhí)行回調(diào)函數(shù):
var callback = function(){
// Handler when the DOM is fully loaded
};
if (
document.readyState === "complete" ||
(document.readyState !== "loading" && !document.documentElement.doScroll)
) {
callback();
} else {
document.addEventListener("DOMContentLoaded", callback);
}
包括domReady](https://github.com/ded/domready)庫(kù)蒸矛,已經(jīng)實(shí)現(xiàn)了這個(gè)解決方案瀑罗。
老版本的IE瀏覽器
對(duì)于IE8及以下的瀏覽器胸嘴,你能使用onreadystatechange
事件去監(jiān)聽(tīng)文檔的readyState
屬性:
document.attachEvent("onreadystatechange", function(){
// check if the DOM is fully loaded
if(document.readyState === "complete"){
// remove the listener, to make sure it isn't fired in future
document.detachEvent("onreadystatechange", arguments.callee);
// The actual handler...
}
});
或者你可以使用Load事件,如jQuery斩祭,這樣可以在任何瀏覽器上運(yùn)行劣像。這也會(huì)導(dǎo)致一個(gè)時(shí)間延遲,因?yàn)樗鼤?huì)等待所有的資產(chǎn)被加載摧玫。注意耳奕,在這個(gè)解決方案中你也要檢查readyState
,如上文所述诬像,這樣能確蔽萑海回調(diào)總是能夠被執(zhí)行。
總結(jié)
如果你正在尋找一種原生js替代ready
方法坏挠,你可以結(jié)合DOMContentLoaded
事件一起處理芍躏。如果你的系統(tǒng)需要兼容IE話,你要確保DOM加載完成降狠。