1. 程式人生 > >前端JS的載入方式?JS的非同步載入

前端JS的載入方式?JS的非同步載入

過多js載入會影響頁面效率,一旦網速不好,那麼整個網站將等待js載入而不進行後續渲染等工作。 有些工具方法需要按需載入,用到再載入,不用不載入。預設正常模式下,JS是同步載入的,即優先載入JS,只有當JS檔案下載完,dom和css才開始載入,當某些時候我們需要JS非同步載入,我們可以設定非同步載入。

不同情況下選取不同方式即可。

一:同步載入

我們平時使用的最多的一種方式。

<script src="http://aaaa.com/script.js"></script>
 
<script src="http://bbbb.com/script.js"></script>
 
<script src="xxx/script.js"></script>
 
<script src="xxx/xxx/script.js"></script>

同步模式,又稱阻塞模式,會阻止瀏覽器的後續處理,停止後續的解析,只有噹噹前載入完成,才能進行下一步操作。

所以默認同步執行才是安全的。但這樣如果js中有輸出document內容、修改dom、重定向等行為,就會造成頁面堵塞。所以一般建議把

二:非同步載入

非同步載入又叫非阻塞載入,瀏覽器在下載執行js的同時,還會繼續進行後續頁面的處理。

1.async 和 defer 屬性 defer:

defer屬性宣告這個指令碼中將不會有 document.write 或 dom 修改。
瀏覽器將會並行下載 js 和其它有 defer 屬性的script,而不會阻塞頁面後續處理。
defer屬性在IE 4.0中就實現了,它提示瀏覽器這個 script 不會產生任何文件元素(沒有document.write),因此瀏覽器會繼續後續處理和渲染。相容所有瀏覽器 。
所有的defer 指令碼保證是按順序依次執行的。

async: async屬性是HTML5新增屬性,IE9+瀏覽器支援 async屬性規定一旦指令碼下載完成則儘快使用,會非同步執行 async屬性僅適用於外部指令碼 此方法不能保證指令碼按順序執行 它們將在onload事件之前完成 總結:可以同時使用 async 和 defer。

      如果沒有 async 屬性 但是有 defer 屬性,那麼script 將在頁面parse之後執行。
      如果同時設定了二者,那麼 defer 屬性主要是為了讓不支援 async 屬性的老瀏覽器按照原來的 defer 方式處理。

2.Script DOM Element

	(function() {
	     var st = document.createElement('script');
	     st.type = 'text/javascript';
	     st.async = true;
	     st.src = 'http://aaaa.com/script.js';
	     var x = document.getElementsByTagName('script')[0];
	     x.parentNode.insertBefore(st, x);
	   //x.insertBefore(st, x.firstChild); 
	 })();

缺點:這種載入方式執行完之前會阻止onload事件的觸發,而現在很多頁面的程式碼都在onload時還執行額外的渲染工作,所以還是會阻塞部分頁面的初始化處理。

3.onload 時的非同步載入

(function() {
     function async_load(){
         var s = document.createElement('script');
         s.type = 'text/javascript';
         s.async = true;
         s.src = 'http://xxx/script.js';
         var x = document.getElementsByTagName('script')[0];
         x.parentNode.insertBefore(s, x);
     }
     if (window.attachEvent)
         window.attachEvent('onload', async_load);
     else
         window.addEventListener('load', async_load, false);
 })();

這種方法只是把插入script的方法放在一個函式裡面,然後放在window的onload方法裡面執行,這樣就解決了阻塞onload事件觸發的問題。

DOMContentLoaded 與 OnLoad 事件 |DOMContentLoaded | 頁面(document)已經解析完成,頁面中的dom元素已經可用。但是頁面中的圖片,視訊,音訊等資源未載入完,作用同jQuery中的ready事件 | |OnLoad |頁面的所有資源都載入完畢(包括圖片)。瀏覽器的載入進度在這時才停止。|

這兩個時間點將頁面載入的timeline分成了三個階段。

4.$(document).ready() 需要引入jquery 相容所有瀏覽器 $(document).ready(function() { alert(“JS載入完成!”); }); 5.由於JavaScript的動態性,還有很多非同步載入方法: XHR Injection、 XHR Eval、 Script In Iframe、 Script defer屬性、 document.write(script tag)。

總結: 對於支援HTML5的瀏覽器,實現JS的非同步載入只需要在script元素中加上async屬性,為了相容老版本的IE還需加上defer屬性; 對於不支援Html5的瀏覽器(IE可以用defer實現),可以採用以上幾種方法實現。 原理基本上都是向DOM中寫入script或者通過eval函式執行JS程式碼,你可以把它放在匿名函式中執行,也可以在onload中執行,也可以通過XHR注入實現,也可以建立一個iframe元素,然後在iframe中執行插入JS程式碼。