最近在作我的项目中登录界面的时候,须要加一我的机验证也就是验证码的功能,和朋友商量再三因为时间有限,便选择引入第三方的验证码。使用过程当中发现,该第三方验证码的实现逻辑基本是先编写指定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