天天看點

用原生 JavaScript 替換 jQuery 的 ready 方法

ready

 方法是 jQuery 實作的在 html 頁面在 DOM(Document Object Model, 文檔對象模型) 樹完全加載完成後觸發的一個方法. 因為它接收的方法在頁面中所有的 DOM 都可通路時才執行, 是以此時你完全可以通路和操作 html 中的元素.

在 jQuery 3.0 之前, 典型的匿名函數方式的用法如下:

$(document).ready(function() {
  // 在 .ready() 被觸發時執行.});      

在 jQuery 3.0 中 ready() 的變化

在 jQuery 3.0 釋出之前, 有以下幾種 

ready

 方法的使用方式:

  • 在 document 對象上: 

    $(document).ready(handler);

  • 在一個空元素上: 

    $().ready(handler);

  • 或直接使用 (即: 不在一個指定的元素上): 

    $(handler);

以上的幾種方式是等價的. 傳入的 handler 會在頁面所有的 DOM 都加載完成後執行, 不管它被哪個指定元素執行. 也就是, 在 p_w_picpath 元素 

$("img")

 與 document 對象上調用 

ready

 方法不表明要等待這些元素加載完成後就觸發 handler, 而是在整個 DOM 樹加載完成後才觸發.

在 jQuery 3.0 中, 除了 

$(handler);

 方法其它的都被棄用了. 官方的理由是:

因為這個選擇與 

.ready()

 方法的行為沒有關系, 它是低效的并且會誤導使用者猜測這個方法的行為.

Ready 和 Load 事件的不同點

ready

 事件在頁面 DOM 完全加載後觸發并能正确的通路到元素. 而 

load

 事件在頁面 DOM 及資源檔案(圖檔,視訊等)都加載完成後才觸發.

load 事件可以像下面這樣使用:

$(window).on("load", function(){
  // 當頁面所有資源(圖檔,視訊等)全加載完成後才加載執行});      

這會等待 DOM 加載完成以及圖檔加載完成(根據圖檔的大小, 需要加載一定的時間).

對于正常的 DOM 操作你多半不需要 

load

 事件, 但如果你想做一個等待頁面所有資源加載的一個加載效果或者是計算圖檔的大小時這應該是一個不錯的選擇.

你可能并不需要 jQuery.ready()

ready

 方法確定了其内部的代碼都能正确的操作 DOM 元素. 這是什麼意思? 當你把 JavaScript 代碼放到 HTML 文檔中時它會確定回調函數裡面的代碼在浏覽器在已經加載頁面中所有的元素時執行:

<!doctype html><html>
  <head>
    <meta charset="utf-8">
    <title>.ready() 教程</title>
    <script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
    <script>
      $(function(){ // .ready() 的回調方法, 在 DOM 完全加載完後執行
        var length = $("p").length;
        // 下面會在console控制台中輸出 1, 表示有段落 p 存在.
        // 這就證明了這個回調方法在 DOM 完全加載完後執行.
        console.log(length);
      });
    </script>
  </head>
  <body>
    <p>I'm the content of this website</p>
  </body></html>      

如果你把要執行的 JavaScript 放到 

body

 元素裡面的最後位置, 你就不需要用 

ready()

 方法把代碼包裹在裡面了, 因為在 JavaScript 代碼執行時頁面中所有的元素都已經加載完成, 是以此時你就可以通路或操作元素了:

<!doctype html><html>
  <head>
    <meta charset="utf-8">
    <title>.ready() 教程</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;
      // 下面會在console控制台中輸出 1, 表示有段落 p 存在.
      console.log(length);
    </script>
  </body></html>      

使用原生 JavaScript 替換 ready()

對于現代浏覽器, 以及 IE9+, 你可以監聽 

DOMContentLoaded

 事件:

document.addEventListener("DOMContentLoaded", function(){
  // 在 DOM 完全加載完後執行});      

在這裡要記住當事件已經觸發後回調方法不會執行(頁面觸發事件後才添加的這個事件監聽). 為了確定回調函數始終能執行, jQuery 檢測了document 的 

readyState

 屬性(參考), 如果檢測出的屬性值是 

complete

 就立即執行回調函數:

var callback = function(){
  // 在 DOM 完全加載完後執行};if (
    document.readyState === "complete" ||
    (document.readyState !== "loading" && !document.documentElement.doScroll)) {
  callback();} else {
  document.addEventListener("DOMContentLoaded", callback);}      

你應該始終記得引入 domReady 庫, 它已經實作了這個解決方案.

老版本的 IE

對于 IE8 及以下版本, 你可以使用 

onreadystatechange

 事件來檢測 document 的 

readyState

 屬性:

document.attachEvent("onreadystatechange", function(){
  // 檢測 DOM 是否加載完全
  if(document.readyState === "complete"){
    // 為了確定在之後不會再觸發 移除事件監聽
    document.detachEvent("onreadystatechange", arguments.callee);
    // 實際處理程式...
  }});      

結論

繼續閱讀