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 的用法有三種:
- $(document).ready(handler)
- $().ready(handler)
- $(handler)
是不是在第一個 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,有興趣的話可以找一下 EricSK 的 Modernier 源碼剖析文章。
我是 K,以前幻想著可以做些偉大的事。但發現把一件簡單的事情做到很好就是一件很難又很厲害的事。所以現在正處於一個把簡單的事情做好的狀態。