最近在作我的項目中登錄界面的時候,須要加一我的機驗證也就是驗證碼的功能,和朋友商量再三因爲時間有限,便選擇引入第三方的驗證碼。使用過程當中發現,該第三方驗證碼的實現邏輯基本是先編寫指定id的HTML標籤,而後加載該第三方的js,由其本身渲染而成,所以借這個機會,再次學習總結一下傳統的<script>標籤加載 JavaScript 腳本相關知識,主要是defer,async屬性。javascript
爲了更好的理解腳本加載的知識,首先簡單瞭解一下HTML頁面處理過程:(關於解析,請看下文script的內容)html
在這個過程當中,普通腳本文件的下載和執行會阻塞文檔的渲染,若是控制得很差,在用戶體驗上就會形成必定程度的影響
所以,大多提倡將腳本加載放在頁面末尾,通常是</body>處:前端
雅虎軍規第18條:把腳本放在底部
腳本加載實例:java
<!-- 頁面內嵌的腳本 --> <script type="application/javascript"> // module code </script> <!-- 外部腳本 --> <script type="application/javascript" src="path/to/my.js"> </script>
沒有 defer 或 async修飾,瀏覽器會當即加載並執行指定的腳本,「當即」指的是在渲染該 script 標籤後面的文檔元素以前,也就是說不等待後續載入的文檔元素,讀到就加載並執行。
若是解析遇到多個<script>標籤,依次加載順序執行。
*此操做會阻止後續文檔元素的解析和渲染,可是這裏有一個預解析的概念
(Webkit 和 Firefox 都進行了這項優化。在執行腳本時,其餘線程會解析文檔的其他部分,找出並加載須要經過網絡加載的其餘資源。經過這種方式,資源能夠在並行鏈接上加載,從而提升整體速度。請注意,預解析器不會修改 DOM 樹,而是將這項工做交由主解析器處理;預解析器只會解析外部資源(例如外部腳本、樣式表和圖片)的引用。)*segmentfault
若是script標籤設置了該屬性,則瀏覽器會異步的下載該文件而且不會影響到後續DOM的渲染;
若是有多個設置了defer的script標籤存在,則會按照順序執行全部的script;
defer腳本會在文檔渲染完畢後,DOMContentLoaded事件調用前執行。
注意:瀏覽器
*在現實當中,延遲腳本並不必定會按照順序執行,也不必定會在 DOMContentLoaded事件觸發前執行,所以最好 只包含一個延遲腳本。 澤卡斯(Zakas. Nicholas C.). JavaScript高級程序設計(第3版) (圖靈程序設計叢書)
async的設置,會使得script腳本異步的加載並在容許的狀況下執行,也就是說加載和渲染後續文檔元素的過程將和script加載並行進行
async的執行,並不會按着script在頁面中的順序來執行,而是誰先加載完誰執行。服務器
因爲是模塊化開發,在此採用的是再模塊內經過動態方式加載第三方的驗證碼js,主要代碼以下。網絡
function load (el, src, callback) { if (!src) { return; } // _verifyExist(src); let scriptHeat = document.createElement('script'); scriptHeat.type = 'text/javascript'; scriptHeat.src = src; scriptHeat.defer = true; /* 爲保證兼容性,在此對回調包裝, */ isFunction(callback) && addOnloadHandler(scriptHeat, callback); el.appendChild(scriptHeat); } function isFunction (fn) { return Object.prototype.toString.call(fn) === '[object Function]'; } function addOnloadHandler (el, callback) { el.onload = el.onreadystatechange = function () { if (!this.readyState || // 這是FF的判斷語句,由於ff下沒有readyState這人值,IE的readyState確定有值 this.readyState === 'loaded' || this.readyState === 'complete' // 這是IE的判斷語句 ) { callback(); } }; }
爲保證該第三方庫執行時有其渲染的元素,因此設置爲defer。可能引起問題是若是網絡慢或其餘緣由會致使該驗證控件呈現較慢(暫時未遇到),因此項目中也加了遮罩處理。app