持續討論 javascript 如何控制最佳化頁面 js 載入順序

來源:互聯網
上載者:User

學習js的時候,經常會遇到這樣的問題,如何控制dom、js在頁面上的載入順序。
Peter Michaux  有一篇文章非常具體地分析了各種控制 js 裝載過程的方法和優劣。
結合他的一些做法分析了一下,大致是這樣的思路。

首先可能會用到 defer來強制頁面載入完成後來再運行js,像這樣:

<script src="x.js" type="text/javascript" defer></script>

看似用起來沒什麼問題,但是發現無法相容Mozilla。

既然這樣不行,就只好換種方法,利用 window.onload 來捕獲頁面的載入事件。
在js檔案裡:

window.onload = function() {
 alert("load over");
}

這一切的一切想必大家都是很熟悉的了,但是,之後就沒有問題了嗎?假設頁面dom裡有一張圖片,像這樣:

<img src="picture.jpg" >

而這張圖片又非常之大,那麼在dom載入完畢之前,js是無法執行的。問題就在於假設dom提供了使用者互動的功能。例如按鈕,輸入表單等,這個時候他們已經是被呈現了的,因此就很有可能產生無效的使用者行為。
我們不能指望使用者會安分守己地等待頁面顯示載入完畢後再發生動作,而要把使用者考慮成隨時隨刻會到處亂點的朋友。

這個問題又如何解決呢?既然我們需要頁面結構輸出後執行js,我們不妨把js入口函數定義在頁面最下面好了。

<head>
  <script src="x.js" type="text/javascript"></script>
</head>
<body>
  ......
  <img src="picture.jpg" >
  <script type="text/javascript">init();</script>
</body>

這樣就達到我們的目的了,頁面結構輸出完畢後就執行js,不用考慮圖片的載入。

但是在文檔末尾嵌入一條js指令碼,畢竟容易被忽略,把關鍵的程式入口放在這種渺小的角落,總覺得不太合適。那有什麼預留退路的方法沒有呢?
我們可以把結尾的指令碼稍微修改一下:

<head>
  <script src="x.js" type="text/javascript"></script>
</head>
<body>
  ......
  <img src="picture.jpg" >

  <script type="text/javascript">window.onload();</script>

</body>

而在js裡預先把入口定義給onload事件:

window.onload = function() {
 alert("load over");
}

這時候頁面結構載入完畢後就會調用onload函數,而即使漏寫了dom裡的onload入口,js自身裡的onload定義也會在頁面載入完畢後執行,這樣退路就留出來了。
不過這時候有個問題,onload事件會執行兩次,可以在js的onload實現裡解決這個問題,改成這樣:

var flag = false;
window.onload = function() {
  if (flag) {return;}
  flag= true;
  alert("load over");
}

這樣似乎已經解決我們所有的問題了,不過仍然有些小遺憾,因為最後一行代碼,致使行為與結構沒有分離開來,要 unobtrusive 就要 unobtrusive 的徹底,為了達到完美的分離,還有很大的討論空間。

而對於js檔案內部的onload事件,我們還可以參考 Simon Willison  的addLoadEvent函數來最佳化:

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

然後,我們就可以在js裡肆無忌憚地不停地將各個不同的函數添加到onload事件響應中了:

addLoadEvent(funcA);
addLoadEvent(funcB);
addLoadEvent(funcC);

當然,同一個js裡設定多個onload響應函數其實沒什麼必要,我們完全可以把funcA、funcB、funcC封裝在一個函數裡add,addLoadEvent函數,更理想的狀態是為頁面動態調用的多個js檔案添加入口。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.