経験総括:必要に応じてJSとcssをロードする

8589 ワード

プロジェクトでは、すべてのページがSSIコマンドincludeというpublic-jsを介しています.shtmlは、関連するjs(共通のスクリプト検証プラグインカスタムコンポーネントなど)を導入するために使用されますが、インタラクティブな効果のないページではこれらのスクリプトを使用する必要がないため、スクリプトの冗長性が大きくなります(キャッシュから読み取ることができますが、使用されていないスクリプトをできるだけ減らすほうがいいです).
public-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などのモジュール化管理プラグインを使わない場合でも、このような方式でよいと思います.