1. 程式人生 > 實用技巧 >非同步載入

非同步載入

doomTree 將jhtml結構按樹的方式掛起來(深度優先原則,先看左側,再看右側)

          html

      head              body

title          meta      div      p

                  a       

csstree 當domtree形成後,會形成一個與domtree相類似的csstree

doomtree+csstree=randertree,然後再繪製網頁

當對domtree進行改變時,randertree就會改變,所以

reflow(重排)(dome節點的刪除,新增,dom節點的寬高變化,位置變化 offsetwidth offsetleft)程式設計要儘量避免重排

repaint(重繪 比如改一個字型顏色,背景圖片)

js載入缺點:載入工具方法沒有必要阻塞文件,過多js載入會影響頁面效率,一旦網速不好那麼整個網站將會等待js載入而不進行後續渲染等工作

js單執行緒載入阻塞頁面的原因:js檔案就中有部分是改變頁面效果的,所以當html渲染還沒完成頁面結構就改變了,所以就等js載入完再渲染頁面

有些工具方法需要按需載入,用到就載入,沒用就不載入

非同步載入的三種方法

1.defer 再引入js的script裡面寫屬性defer,只有IE能用可以將程式碼寫在內部,要等到整個頁面解析完畢時,就是domtree生成的時候

2.async,同樣在script裡面寫async屬性(w3c標準方法,)只能載入外部指令碼,不能在內部寫程式碼,載入完就執行

3.建立script插入到Dom中,載入完後callback

var script =document。createElement(“script”)

  script.src="js檔案"

  document.head.appernChild("script")

封裝函式:

function loadScript(url,callback){
    var script =document.createElement(“script”)
    if(script.readyState){
        script.onreadystatechange
=function(){//相容IE if(script.readyState=="complete"||script.readyState=="loaded"){ callback(); } } }else{ script.onload=function(){ callback(); } }   script.src="js檔案" document.head.appernChild("script") }

如果要執行這個函式,

loadScript(檔名,檔案中的某個函式名)//這樣執行會報錯,因為當第二個引數傳進來的時候,不認識,
所以應該像下面那樣寫
loadScript(url,function(){
  檔案中的某個函式()
})

時間線

1.建立Document物件,開始解析web頁面。解析HTML元素和他們
的文字內容後,新增Element物件和Text節點到文件中 這個階段
document.readyState="loading"
2.遇到link外部css,建立執行緒載入,並繼續解析文件
3.遇到script外部js,並且沒有設定有async defer,瀏覽器載入,並且阻塞
等待js載入完成並執行該指令碼,然後繼續解析文件
4.遇到script外部指令碼js,並且設定有async defer,瀏覽器建立執行緒載入,並繼續解析文件
對於async屬性的指令碼,指令碼載入完成後立即執行。(非同步禁止使用document.write()//因為這個方法如果在整個文件解析完後再執行,會把前面所有的文件流都清除)
5.當遇到img等,先正常解析dom結構,然後瀏覽器非同步載入src,並繼續解析文件
6.當文件解析完成後,document.readyState="interactive"
7.文件解析完成後,所有設定有defer的指令碼會按照順序執行。注意與async
8.document物件觸法DOMContentLoaded事件,也標誌著程式執行從同步指令碼執行階段,轉化為事件驅動階段
9.當所有async的指令碼載入完成並執行後,img等載入完成後,document.readyState="complete",windown物件觸發load事件
10.從此,以非同步響應方式處理使用者輸入,網路事件