【譯】用原生javascript代替jQuery的Ready()方法

本文轉(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加載完成降狠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末对竣,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子榜配,更是在濱河造成了極大的恐慌否纬,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛋褥,死亡現(xiàn)場(chǎng)離奇詭異临燃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)烙心,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)谬俄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人弃理,你說(shuō)我怎么就攤上這事溃论。” “怎么了痘昌?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵钥勋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我辆苔,道長(zhǎng)算灸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任驻啤,我火速辦了婚禮菲驴,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘骑冗。我一直安慰自己赊瞬,他們只是感情好先煎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著巧涧,像睡著了一般薯蝎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谤绳,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天占锯,我揣著相機(jī)與錄音,去河邊找鬼缩筛。 笑死消略,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瞎抛。 我是一名探鬼主播艺演,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼婿失!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起啄寡,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤豪硅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后挺物,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體懒浮,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年识藤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砚著。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痴昧,死狀恐怖稽穆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赶撰,我是刑警寧澤舌镶,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站豪娜,受9級(jí)特大地震影響餐胀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瘤载,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一否灾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸣奔,春花似錦墨技、人聲如沸惩阶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)琳猫。三九已至,卻和暖如春私痹,著一層夾襖步出監(jiān)牢的瞬間脐嫂,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工紊遵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留账千,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓暗膜,卻偏偏與公主長(zhǎng)得像匀奏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子学搜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 原文鏈接 http://blog.poetries.top/2016/10/20/review-jQuery 關(guān)注...
    程序員poetry閱讀 16,647評(píng)論 18 503
  • 1.JQuery 基礎(chǔ) 改變web開(kāi)發(fā)人員創(chuàng)造搞交互性界面的方式娃善。設(shè)計(jì)者無(wú)需花費(fèi)時(shí)間糾纏JS復(fù)雜的高級(jí)特性。 1....
    LaBaby_閱讀 1,341評(píng)論 0 2
  • 一瑞佩、樣式篇 第1章 初識(shí)jQuery (1)環(huán)境搭建 進(jìn)入官方網(wǎng)站獲取最新的版本 http://jquery.co...
    凜0_0閱讀 3,390評(píng)論 0 44
  • 有一個(gè)壞習(xí)慣聚磺。 保存舊東西。 備忘錄記錄下每天做的事炬丸,每天的感想瘫寝。倒計(jì)時(shí)里存著一直以來(lái)的記錄。會(huì)把拍過(guò)的照片全都存...
    柒七SyQk閱讀 769評(píng)論 0 50
  • 形容一個(gè)人得用她自己的話來(lái)說(shuō)最為貼切稠炬,大黃在自己的動(dòng)態(tài)上這么說(shuō)道:有些姑娘是可以說(shuō)污段子把男生說(shuō)的害羞的不要不要的...
    方知友閱讀 896評(píng)論 1 3