关于按需加载js,从而提高页面加载性能:
以京东商品详情页面为例:
首次打开时,会加载一部分js,当下拉滚动条时,会促发事件,从而以jsponp形式异步加载一些js文件,如评论调用的js文件:
http://club.360buy.com/clubservice/newproductcomment-681391-3-0.html?callback=fetchJSON_CommentList(这个链接会被调用,从而加载对应的json数据,再配合实现先好的jsonp处理函数去处理,把结果赋值到对应的位置:
如下是fetchJSON_CommentList实现写好的回调函数
$(".btn-comment").livequery("click",
function() {
var a = $(this).attr("href");
$.extend(jdModelCallCenter.settings, {
clstag1: 0,
clstag2: 0,
fn: function() {
jdModelCallCenter.autoLocation(a)
}
});
jdModelCallCenter.settings.fn();
return false
});
var CommentList = {
getData: function(b, c, d) {
var f = this,
b = b || 0,
c = c || 0,
d = d,
a = "http://club.360buy.com/clubservice/newproductcomment-" + G.sku + "-" + b + "-" + c + ".html";
if (b == 1) {
b = 3
} else {
if (b == 3) {
b = 1
}
}
window.fetchJSON_CommentList = function(g) {
if (!$("#comment .mc").hasClass("loaded")) {
if (parseInt(g.CommentSummary.CommentCount) !== 0) {
$("#comment").show();
$("#comment .mc").addClass("loaded").html(commentRate_TPL.process(g))
} else {
$("#comment").attr("nodata", "true").hide()
}
$("#comments-list .tab li").each(function() {
var j = $("#comments-list .tab li").index($(this)),
h = $(this).find("em");
switch (j) {
case 0:
h.html("(" + g.CommentSummary.CommentCount + ")");
break;
case 1:
h.html("(" + g.CommentSummary.GoodCount + ")");
break;
case 2:
h.html("(" + g.CommentSummary.GeneralCount + ")");
break;
case 3:
h.html("(" + g.CommentSummary.PoorCount + ")");
break;
case 4:
h.html("(" + g.CommentSummary.ShowCount + ")");
break
}
})
}
f.setItem(d, g, b, c)
};
$.getJSONP("http://club.360buy.com/clubservice/newproductcomment-" + G.sku + "-" + b + "-" + c + ".html?callback=fetchJSON_CommentList")
},
setItem: function(f, d, a, c) {
var j = this,
b = f,
a = a || 0,
c = c || 0,
h = f.attr("id"),
g = "";
f.html(commentList_TPL.process(d));
switch (h) {
case "comment-0":
g = "CommentCount";
break;
case "comment-1":
g = "GoodCount";
break;
case "comment-2":
g = "GeneralCount";
break;
case "comment-3":
g = "PoorCount";
break;
case "comment-4":
g = "ShowCount";
break;
default:
g = "CommentCount"
}
$("#commentsPage" + d.Score).pagination(d.CommentSummary[g], {
items_per_page: 7,
num_display_entries: 5,
current_page: c,
num_edge_entries: 2,
link_to: "#comments-list",
prev_text: "\u4e0a\u4e00\u9875",
next_text: "\u4e0b\u4e00\u9875",
ellipse_text: "...",
prev_show_always: false,
next_show_always: false,
callback: function(k, l) {
if (a == 1) {
a = 3
} else {
if (a == 3) {
a = 1
}
}
j.getData(a, k, b)
}
})
}
};
以下参考:
http://www.aichengxu.com/article/Javascript/610_7.html
s无非就是script标签引入页面,但当项目越来越大的时候,单页面引入N个js显然不行,合并为单个文件减少了请求数,但请求的文件体积却很大。 这时候最好的做法就是按需引入,动态引入组件js和样式,文件load完成后调用callback,运行js。代码还是很简便的 1. 判断文件load完成。加载状态ie为onreadystatechange,其他为onload、onerror if(isie){ Res.onreadystatechange = function(){ if(Res.readyState == 'complete' || Res.readyState == 'loaded'){ Res.onreadystatechange = null; callback(); _self.loadedUi[modelName] = true; } } }else{ Res.onload = function(){ Res.onload = null; callback(); _self.loadedUi[modelName] = true; } Res.onerror = function(){ throw new Error('res error:' + modelName+'.js'); } } 2. 所有组件的命名最好保持一致,callback调用也比较方便。还可以根据需要增加参数比如: requires,依赖于那些文件;style,true || false,是否加载样式,等等。 3. 移除操作也可以有,移除script、style标签、delete组件 (function(window,undefined){ if(!window.ui) { window.ui = {}; } //动态加载ui的js window.bus = { config : { version : window.config.version, cssPath : window.config.resServer + '/css/v3/ui', jsPath : window.config.resServer + '/js/v2/ui' }, loadedUi : {}, readyStateChange : function(){ var ua = navigator.userAgent.toLowerCase(); return ua.indexOf('msie') >= 0; }, loadRes : function(modelName,prames,callback){ var _self = this; var Res = document.createElement(prames.tagName); for(var k in prames){ if(k != 'tagName'){ Res.setAttribute(k,prames[k],0); } } document.getElementsByTagName('head')[0].appendChild(Res); if(this.readyStateChange()){ Res.onreadystatechange = function(){ if(Res.readyState == 'complete' || Res.readyState == 'loaded'){ Res.onreadystatechange = null; callback(); _self.loadedUi[modelName] = true; } } }else{ Res.onload = function(){ Res.onload = null; callback(); _self.loadedUi[modelName] = true; } Res.onerror = function(){ throw new Error('res error:' + modelName+'.js'); } } }, removeUi : function(modelName){ if(!modelName){ return true }; this.loadedUi[modelName] = false; var head = document.getElementsByTagName('head')[0]; var model_js = document.getElementById('J_model_'+modelName + '_js'); var model_css = document.getElementById('J_model_'+modelName + '_css'); if(model_js && model_css){ delete window.ui[modelName]; head.removeChild(model_js); head.removeChild(model_css); return true; }else{ return false; } }, loadUi : function(modelName,callback,setting){ if(!modelName){ return true }; callback = callback || function(){}; if(this.loadedUi[modelName] == true){ callback(); return true } var deafult_setting = { style : true, js : true, requires : [] } for(var key in setting){ deafult_setting[key] = setting[key]; } deafult_setting['style'] === true && this.loadRes(modelName,{ id : 'J_model_'+modelName + '_css', name : modelName, tagName : 'link', type : 'text/css', rel : 'stylesheet', href : this.config.cssPath + '/' + modelName + '.css?v=' + this.config.version }); deafult_setting['js'] === true && this.loadRes(modelName,{ id : 'J_model_'+modelName + '_js', name : modelName, tagName : 'script', type : 'text/javascript', src : this.config.jsPath + '/' + modelName + '.js?v=' + this.config.version },callback); if(deafult_setting.requires.length > 0){ for(var i=0,len = deafult_setting.requires.length;i<len;i++){ this.loadUi(deafult_setting.requires[i]); } } } } })(window) 使用方法 // load comment for feed window.bus.loadUi('new_comment_feed', function(){ window.ui.new_comment_feed($("#J_newsList")); },{ style : false, requires:['emoticon','addFriend'] }); // load new yy ui window.bus.loadUi('yy', function(){ window.ui.yy(options); },{ style:false, requires:['emoticon'] }); // load photoLightbox window.bus.loadUi('photoLightbox', function(){ window.ui.photoLightbox(options.urlAjaxGetFriendPhoto, options.urlCommentOtherPhoto,$("#J_newsList"),options.myUid,options.myName); });