jQuery 原始碼解讀 (III) – ready 解析

 

Ready . Set . Go

jQuery 原始碼解讀 (I) / (II) 看完了 jQuery 進入點的部分之後,我們來看看使用 jQuery 的時候 99.9% 的人一定會在一開始的時候就呼叫的一個 method:

.ready(handler)  

如果你剛好是那 0.1% 的人沒用,放心 jQuery 自己也會幫你呼叫 🙂 jQuery 自己會在一開始就先偷偷註冊兩個 onReady handler 去做 browser feature detection。

.ready 的用法有三種:

  1. $(document).ready(handler) 
  2. $().ready(handler)
  3. $(handler)
前兩個方法,如 jQuery 原始碼解讀 (II) 所講的會去呼叫 jQuery.fn.init 然後以傳入的第一個參數當作 selector,由於 document 本身就是一個 DOMNode 所以直接就是回傳 context 為 document 的 jQuery object instance,而 $() 則是回傳一個空的 context 的 jQuery object instance,但因為 .ready 其實跟 jQuery object 本身綁定的 context 無關,所以其實你傳什麼 selector 進去都可以直接呼叫 .ready 。但是除了 document 或是 null/””/undefined 之外的 selector 在 ready 前其實都不會 work,所以基本上就只能 $(document) 或是 $()。 

至於第三個方法,其實只是 jQuery 故意留一個 shortcut,但感覺好像也沒什麼必要


 

而且這個 shortcut 的 condition check branch 是在最後一段,所以其實效能是最差的,但是 jQuery 官方文件反而是建議不要使用第二個方法?有點不解。綜合 jQuery 文件跟筆者小小的看法,我們還是用第一個好了 🙂
不過,以筆者的個人看法,第二個方法效能才是上等的建議啊,不然客倌您看:


是不是在第一個 if 的時候就回來了!

接著來看看 .ready 裡面做了什麼事情:

看得出來這邊的重點在於使用了 readyList 來追蹤所有的 onReady handler,而 readyList 是一個 jQuery.Callbacks 回傳的 object instance,傳入的參數是以空格分隔的, once memory 代表的意思是當 fire 過一次就失效。 Callbacks 基本上很類似一個 array 裡面存放 function references,同時加上一些 fire event 的處理。之後當收到 DOMContentLoaded event 的時候就可以透過這個 readyList 去 fire 所有已註冊的 on ready hanlders。

之後接著檢查如果已經是在 complete 的 readyState 下,那就直接觸發 jQuery.ready。
正常情況下則是去註冊 DOMContentLoaded 去觸發 jQuery.ready,然後後面再註冊 load event 以避免在某些瀏覽器沒有 DOMContentLoaded 的 support 的情況下整個程式就不會動了。 DOMContentLoaded 與 load 的差別在於 DOMContentLoaded 會在所有的 DOM nodes 都 ready 的時候觸發,而 load 則是必須在所有的 Node 的內容都 ready 才會觸發。比如說你的網頁中有放 ,那麼 DOMContentLoaded 觸發的時候 的圖片內容一定是還沒觸發,但 load 被觸發的時候一定是在 圖片已經完全載入的時候。所以如果你預計再圖片載入完之後去計算出新的 layout,那你就不能用 .ready 而要改用 .load。

另外一點值得提的是,也可以對 img element 註冊 load 事件,但是 load 無法處理瀏覽器 cached images,也就是說如果你預期每次都要收到 img 的 onload 事件來做一些運算去重新 layout 的話,一定會遇到很多問題,比如 Pinterest like 的 layout 就必須取得每一張圖片的大小來計算每一個 Pin 的高度,這時候單純依賴 load 就會有問題。因此有了一個對應的 Plugin – imageloaded 來幫忙處理 image 的 load event。

至於前面提到的 jQuery 會自己註冊的 feature detection 的 function 可以參考這個 gist: https://gist.github.com/3183078,裡面會做以下 features 的偵測:

偵測的技巧是值得學習的,原理大概是建立一個 DOM element,並加入 DOM tree,再重這個 DOM node 的屬性或是 computedStyle 去偵測 feature。相關的技巧應用的很完整的是 Modernizr,有興趣的話可以找一下 EricSKModernier 源碼剖析文章。

 

jQuery 系列文章:


Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *