HTML中script标签加载问题
HTML文档为一行一行从上往下加载。当加载到script标签时会停下所有加载等待script加载完毕,当script放在head标签中时,用户加载网页时会先加载script标签,使得body中的内容没法第一时间加载,导致页面处在一片空白状态下,直到script加载完毕。
在头文件的script全部加载完毕前浏览器会处于阻塞状态,而页面内容都在body标签中,如果将script标签全部放在head标签中会导致用户在script加载完毕前处于空白界面无法进行交互。
解决办法:将script放在body标签底部
为了避免这种情况应该尽量将script放在body标签的底部,先加载界面内容再加载script。
发起http请求会有时间损耗,会导致下载一个100kb的文件所需时间小于下载4个25kb的文件所需时间。所以需要尽量将外联js文件合并,减少下载次数。但需要注意的是,js会阻塞浏览器,虽然一次下载完所有的js文件会减少http的时间损耗,但是js文件越大阻塞浏览器的时间就越大。所以好一点的办法就是逐步添加script。具体实现方法如下所示。
1. 延期脚本
Html4为script增加了一种新的属性defer,可以使script延期加载。
<script type="text/javascript" src="test.js" defer> </script>
2. 动态脚本元素
Dom允许动态加载脚本,我们可以动态加载script标签。
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "test.js"; document.getElementsByTagName("head")[0].appendChild(script);
此文件当元素添加到文档中后会立刻启动下载,此技术重点在于无论在何处下载,文件的下载和运行都不会阻塞页面其他内容。
动态添加元素在加载完毕后会发出一个load事件。
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "test.js"; script.onload = function() { alert("script is readly"); } document.getElementsByTagName("head")[0].appendChild(script);
ie没有onload事件。有差不多功能的onreadystatechange事件
var script = document.createElement("script"); script.type = "text/javascript"; script.src = "test.js"; script.onreadystatechange = function() { if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; alert("script is readly"); } }
为了兼容,所以将两个函数整合成如下函数
function loadScript(url, callback){ var script = document.createElement ("script") script.type = "text/javascript"; if (script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { //Others script.onload = function(){ callback(); }; } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
在使用时可以直接使用script下载仅仅含有loadScript的js文件,然后用loadScript函数去下载其他标签。
<script type="text/javascript" src="loader.js"></script> <script type="text/javascript"> loadScript("test.js", function(){ alert(‘test alert ready‘) }); </script>