無阻塞的腳本是創建響應迅速的web應用的第一步,其祕訣就是在頁面加載完成後才加載JS,也就是儘量在window.onload事件觸發後再下載腳本。
這裏對比幾種無阻塞加載腳本的方法
一、延遲的腳本
使用script擴展屬性defer,由於只有Internet Explorer 支持 defer 屬性,所以基本不建議使用這種方式,使用方法爲:
<script defer="defer">
二、XMLHttpRequest腳本注入技術
用XHR來下載JS文件,然後通過創建動態script元素將代碼注入頁面中:
var xhr = new XMLHttpRequest();
xhr.open("get","file.js",true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4){
//動態添加腳本
var script = document.createElement("script");
script.type = "text/javascript";
script.text = xhr.responseText;
document.body.appendChild(script);
}
}
優點:
1、下載JS但不立即執行,可以把腳本的執行推遲到想執行的時候
2、瀏覽器通用代碼,都能正常工作
缺點:
1、js文件要和請求頁面處於相同的域,因此大型web應用通常不會採用該技術。
2、需要HTTP請求
三、動態腳本加載
可以直接封裝爲一個JavaScript,這裏我直接叫loadScript.js
function loadScript(urlS,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{
script.onload = function(){
callback();
};
}
script.src = urlS;
$("head")[0].appendChild(script);
}
使用方法:
<head>
...
<script src="jq/jquery.min.js"></script>
</head>
<body>
...
<script type="text/javascript">
loadScript("xx.js",function(){
console.log("動態腳本加載完畢,開始執行其腳本里面的方法初始化");
//方法代碼內容
});
</script>
</body>
注意:把loadScript函數直接嵌入頁面,可以避免產生多一次HTTP請求。
優點:
只需要包含loadScript和一些頁面必須腳本代碼,下載執行都非常快
對比可以發現,動態腳本技術的是最最佳方案。下面舉個具體栗子來看看真實動態腳本加載使用。
我改裝一下我之前一篇文章(https://blog.csdn.net/nzzl54/article/details/91040781)寫的html
<head>
...
<link rel="stylesheet" type="text/css" href="ztree/css/zTreeStyle/zTreeStyle.css">
<script src="jq/jquery.min.js"></script>
<script src="loadScript.js"></script>
</head>
<body>
<div>選擇的是:<input id = "xmtShow" type="text" value = "" style="margin-left:10px;margin-top:10px;width: 160px;"></input></div>
<div class = "tree-content scrollbar" style = "margin-top: 40px;">
<input hidden id="xmtHide" name="xmt">
<input id="xmtQuery" type="text" value="" style="margin-left:10px;margin-top:10px;height:18px;line-height:18px;vertical-align:bottom;">
<input id="xmtQbut" class="xmtQbut" type="button" value="查詢">
<input id="xmtCbut" class="xmtQbut" type="button" value="重置">
<ul id="xmtTree" class="ztree scrollbar" style="margin-top:0;">
</ul>
</div>
<script type="text/javascript">
var zNodes = [{id: 1,name: "一級標題1",pId: 0,open:true
}, {id: 2, name: "一級標題2",pId: 0,open:true
}, {id: 3, name: "2.1級標題",pId: 2
}, {id: 4, name: "2.2級標題",pId: 2
}, {id: 5, name: "1.1級標題", pId: 1
}, {id: 6, name: "1.2級標題",pId: 1
}, {id: 7, name: "1.21級標題",pId: 6
}, {id: 8, name: "一級標題3",pId: 0
}, {id: 9, name: "1.22級標題",pId: 6
}, {id: 10, name: "1.221級標題", pId: 9
}, {id: 11, name: "1.2211級標題", pId: 10
}, {id: 12, name: "1.2212級標題", pId: 10 } ];
function setTreeQueryInit(){
var setting = {
view: {
dblClickExpand: false,
showLine: false
},
data: {
simpleData: {
enable: true
}
},
check: {
enable: false,
chkboxType: { "Y": "ps", "N": "s" }
},
callback: {
onClick: myClick,
onCheck: onCheck
}
};
$("#xmtQbut").on('click',function(){//查詢項目
var keyword=$("#xmtQuery").val();
var zNodeQuery=[];
if(keyword!=""){
for(var i=0;i<zNodes.length;i++){
if(zNodes[i].name.indexOf(keyword)!=-1){
zNodeQuery.push(zNodes[i]);
}
}
}
$("#xmtTree").empty();
//alert("123");
$.fn.zTree.init($("#xmtTree"), setting, zNodeQuery);
});
$("#xmtCbut").on('click',function(){//重置項目
$("#xmtQuery").val("");
$.fn.zTree.init($("#xmtTree"), setting, zNodes);
});
}
function myClick(event, treeId, treeNode){
console.log(event);
console.log(treeNode);
var deptId = treeNode.id;
console.log(deptId);
var zTree = $.fn.zTree.getZTreeObj(treeId);
var names = "";
var ids = "";
var nodes;
if (zTree.setting.check.enable == true) {
zTree.checkNode(treeNode, !treeNode.checked, false);
nodes = zTree.getCheckedNodes();
} else{
nodes = zTree.getSelectedNodes();
}
for (var i = 0, l = nodes.length; i < l; i++) {
names += nodes[i].name + ",";
ids += nodes[i].id + ",";
}
if (names.length > 0) {
names = names.substring(0, names.length - 1);
ids = ids.substring(0, ids.length - 1);
}
console.log("names = "+names+",ids = "+ids);
$("#xmtHide").attr("value",names);
$("#xmtHide").attr("ids",ids);
$("#xmtShow").attr("value",names);
$("#xmtShow").attr("ids",ids);
}
loadScript("ztree/js/jquery.ztree.all.js",function(){
console.log("ztree/js/jquery.ztree.all.js動態腳本加載完成");
loadScript("plugin/js/selectTreeM.js",function(){
console.log("動態腳本加載完畢,開始執行其腳本里面的方法初始化");
initTree("xmtTree",zNodes,myClick,false);
setTreeQueryInit();
});
});
</script>
</body>
主要是把引入loadScript.js,然後在script中直接使用器提供的函數來進行動態加載
loadScript("ztree/js/jquery.ztree.all.js",function(){
console.log("ztree/js/jquery.ztree.all.js動態腳本加載完成");
loadScript("plugin/js/selectTreeM.js",function(){
console.log("動態腳本加載完畢,開始執行其腳本里面的方法初始化");
initTree("xmtTree",zNodes,myClick,false);
setTreeQueryInit();
});
});
注意:第三種方法非常適用於一個頁面加載多個JavaScript的情況,不過需要注意好腳本間的關係,就像上面的selectTreeM.js是需要先加載完畢ztree/js/jquery.ztree.all.js才能執行
增強版庫類LazyLoad下載地址:https://github.com/rgrove/lazyload