zoukankan      html  css  js  c++  java
  • 经验总结:按需加载JS和css

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

    public-js.shtml

    <!--#config timefmt="%Y%m%d%H%M%S"-->
    <script type="text/javascript" src="/js/jquery1.6.js?v=<!--#flastmod virtual='/js/jquery1.6.js' -->" ></script>
    <!-- <script type="text/javascript" src="/js/core.js?v=#flastmod virtual='/js/core.js'" ></script>
    -->
    <script type="text/javascript" src="/js/public.js?v=#flastmod virtual='/js/public.js'" ></script>

    <!-- 加载组件 -->

    <!--#include virtual="/include/component.shtml" -->

    <!-- 加载表单验证插件 -->
    <!--#include virtual="/include/nicevalidator.shtml" -->

    <!-- 页面通用函数 -->
    <!--#include virtual="/include/page-js.shtml" -->

    为了实现组件和验证插件的按需加载,定义这么一个函数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)

    ~~~个人认为在不用seaJs requireJs等模块化管理插件的情况下,这种方式也还可以。

  • 相关阅读:
    flex布局
    redis持久化的四种方式
    list all index in elasticsearch
    Java Thread停止关闭
    关于线程的一些操作方法
    将redis key打印到文本
    spout和bolt
    java读取redis的timeout异常
    storm中,ack与fail
    好文要收藏(大数据)
  • 原文地址:https://www.cnblogs.com/stephenykk/p/3655598.html
Copyright © 2011-2022 走看看