经验总结:按需加载JS和css - stephenykk

发布:2016-06-15 08:05   点击1011次   评论:0

http://www.tuicool.com/articles/vuUzea
经验总结:按需加载JS和css - stephenykk

项目中做过这样的事情:所有页面都通过SSI指令 include这样一份public-js.shtml, 用来引入涉及到的js(包括公共的脚本 验证插件 自定义组件等),但是一些没有交互效果的页面根本不需要用到这些脚本,所以造成脚本冗余较大(尽管可以从缓存读取,但还是应该尽量减少没用到的脚本为佳)

为了实现组件和验证插件的按需加载,定义这么一个函数loadJsCss 

/*** js和css按需加载 ***/
function loadJsCss(url, callback ){// 非阻塞的加载 后面的js会先执行
  var isJs = /\/.+\.js($|\?)/i.test(url) ? true : false;
  function Onloaded(script, callback){//绑定加载完的回调函数
    if(script.readyState){ //ie
      script.attachEvent('onreadystatechange', function(){
        if(script.readyState == 'loaded' || script.readyState == 'complete'){
          script.className = 'loaded';
          callback && callback.constructor === Function && callback();
        }
      });
    }else{
      script.addEventListener('load',function(){
        script.className = "loaded";
        callback && callback.constructor === Function && callback();
      }, false); 
    }
  }
  if(!isJs){ //加载css
    var links = document.getElementsByTagName('link');
    for(var i = 0; i < links.length; i++){//是否已加载
      if(links[i].href.indexOf(url)>-1){ 
        return; 
      }
    }
    var link = document.createElement('link');
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = url;
    var head = document.getElementsByTagName('head')[0]; 
    head.insertBefore(link,head.getElementsByTagName('link')[0] || null );
  }else{ //加载js
    var scripts = document.getElementsByTagName('script');
    for(var i = 0; i < scripts.length; i++){//是否已加载
      if(scripts[i].src.indexOf(url)>-1 && callback && (callback.constructor === Function) ){ 
      //已创建script
        if(scripts[i].className === 'loaded'){//已加载
          callback();
        }else{//加载中
          Onloaded(scripts[i], callback);
        }
        return; 
      }
    }
    var script = document.createElement('script');
    script.type = "text/javascript";
    script.src = url; 
    document.body.appendChild(script);
    Onloaded(script, callback); 
    
  }
}

// 表单验证插件 动态加载 
function loadValidator(callback){// 加载nicevalidator插件 
loadJsCss("/css/nicevalidator.css"); 
loadJsCss("/js/nicevalidator.js", callback); 
}

// 组件动态加载 
function loadComponent(callback){// 加载自定义组件 
loadJsCss("/css/component.css"); 
loadJsCss("/js/component.js", callback); 
}

但是发现每个验证方法或组件的调用都要放到回调函数内部,实在笨拙,而且改起来也很麻烦。如:

loadValidator(function(){ $('#frm').validator({...}););

loadComponent(function(){ $.Tab({...}); );

经过尝试发现可以保持页面原有的调用方式,只需在public.js公共js文件中定义相同接口即可:

(function(){
  $.fn.validator = function(){
    var args = arguments, self = this;
    loadValidator(function(){//~~~初始状态fn.validator会请求js和css, 加载后的回调函数重写 fn.validator 为正确的方法
      $.fn.validator.apply(self, args);
    })
  }
  var fnames = ['Tab',"SiceSlider","SiceLvSelect","SiceSelect"];
  $.each(fnames, function(i,fname){//~~~同理 回调函数重写接口为正确的函数
    $[fname] = function(){
      var args = arguments;

      loadComponent(function(){ 
        var Foo = function(){}; Foo.prototype = $[fname].prototype; var foo = new Foo(); // 需要new 的组件,这样获取参数对象
        $[fname].apply(foo,args);  
      });
    }
  });
})(jQuery)

关于 GitHub 导航 部门 反馈

提示:`/home.php`入口数据仅为演示功能,不构成任何交易凭证,也不承担相关风险和责任!

Copyright © 2011-2018 xxxxx.com All rights reserved.

Run:4.387/47.828(ms); 7(sql)/2.889(MB); comm:news/detail; Upd:2024-03-28 22:50:40