web页面优化之动态加载js和文件

关于按需加载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);
}); 

 

posted @ 2013-02-03 16:00  一束光  阅读(692)  评论(0编辑  收藏  举报

友情链接

CFC4N