随着前端应用越来越火,应用越来越复杂,不管是什么系统,javascript开发很容易陷入混乱的状态,各种框架层出不穷,比如目前很火的jquery框架,虽然很是强大,但是在实际使用后,会发现很难完全支持业务的要求,如此扩展是一种很好的途径,然而,对很多人来说, 能完全应用已经很有难度,对其进行扩展完善,那就更难上加难了,在通过了多次的洗礼后,突然有种想要自己写控件框架的冲动,于是有了后续的这些文章。
为了简单起见,先创建如下目录结构。 
 
+--demo 
     +--script 
          +--common 
               +--init.js 
          +--css 
     +--web 
          +--test.html
接着在common目录下添加init.js文件, 该文件,就是我们框架之源,负责加载js, css文件,先定义第一个对象scriptUtil; 
 
复制代码 代码示例:
function scriptUtil() {  
    //加载导入的js列表  
    this.scriptList = {};  
    //加载的css列表  
    this.cssList = {};  
    //创建的控件类  
    this.com = {};  
}; 
因为是第一个js文件,需要手工加载,在web目录下添加test.html文件,源码如下: 
 
复制代码 代码示例:
<!DOCTYPE html>  
  <head><title>test</title>  
    <script src="../script/common/init.js" type="text/javascript"></script>  
  </head>    
  <body>  
  </body>  
</html> 
接下来,为了能够清楚加载的情况, 给对象scriptUtil添加一个日志输出的方法,其次添加一个加载成功的判断函数; 
 
复制代码 代码示例:
scriptUtil.prototype = {  
    /** 
     * 日志输出. 
     * 参数 src 字符串 
     */  
    LogInfo : function(src) {  
        if(window.console.info) {  
            window.console.info(src);  
        }  
    },  
    /** 
     * 是否加载判断. 
     * 参数 src 加载的文件名 
     */  
    isImport : function(src) {  
        return (typeof this.scriptList[src] != "undefined"   
             || typeof this.cssList[src] != "undefined");  
    }//方法之间用逗号隔开  
} 
加载的文件包含js、css两种格式, 因此需要添加一个文件类型判断函数 
 
复制代码 代码示例:
scriptUtil.prototype = {  
    //之前添加过的方法  
    /** 
     * 文件类型.  
     * 参数 scr 
文件路径 
     */  
    scrType : function(scr) {  
        var scrAry = scr.split(".");  
            if (scrAry.length > 1) {  
                return scrAry[scrAry.length - 1].toUpperCase();  
            } else {  
                return "";  
            }  
    } //方法之间用逗号隔开,  
} 
因为使用的是普通的目录结构,因此需要处理相对路径的问题,添加一个获取根目录路径的函数(dome目录)。
说明,首先有两个路径, 一个是html文件的路径 即test.html的路径,另一个是js初始化文件的路径,即init.js的路径,通过这两个文件的路径,用来分析出整个工程的相对路径。 
 
复制代码 代码示例:
scriptUtil.prototype = {  
    //之前添加过的方法  
    getPath : function() {  
                //获取默认的init.js文件路径  
        var srcUrl = document.getElementsByTagName("script")[0].src;  
        var re = /[/]+/g;  
                //判断是否是硬盘,或
服务器上的URL  
        if (/([a-zA-Z]:)|([hH][tT][tT][pP]://)/.test(srcUrl)) {  
                        //获取html的URL  
            var docUrl = document.URL;  
                        //拆分成数组  
            var srcAry = srcUrl.split(re);  
            var docAry = docUrl.split(re);  
            var indexs = 0;  
                        //循环找到第一个不相同的目录  
            for ( var i = 0,   
                len = srcAry.length < docAry.length ? srcAry.length  
                    : docAry.length;   
                    i < len; i++) {  
                if (srcAry[i] !== docAry[i]) {  
                    indexs = i;  
                    
break;  
                }  
            }  
                        //test.html目录回寻到根目录  
            var path = "";  
            for ( var i = indexs, len = docAry.length; i < len - 1; i++) {  
                path = path + "../";  
            }  
                        //完善js的目录  
            for ( var i = indexs, len = srcAry.length; i < len - 1; i++) {  
                path = path + srcAry[i] + "/";  
            }  
            return path;  
        } else {  
                        //如果是相对目录,则直接使用。  
            var srcAry = srcUrl.split(re);  
            var path = "";  
            for ( var i = 0, len = srcAry.length; i < len - 1; i++) {  
                path = path + srcAry[i] + "/";  
            }  
            return path;  
        }  
    },  
} 
有了上面的准备, 接下来开始写这个类的核心函数,即import函数,这里重点讲一下,第一个参数, 可以传一个文件名, 也可以传一个数组, 是数组的情况下, 加载的文件,无论成功还是失败,都会在事件onload 或onerror里接着加载下一个文件,并在已加载列表中,打上标记。
 
复制代码 代码示例:
scriptUtil.prototype = {  
//之前添加过的方法, 用逗号隔开  
    /** 
     * 加载文件, 
     * 参数 src 加载的文件,字符串或数组, 
     * 参数 callBack 
回调函数, 
     * 参数 sPath 指定路径 默认为空 
     */  
    Import : function(src, callBack, sPath) {  
        //路径  
        if(typeof sPath == "undefined") sPath = "";  
        //转换成数组  
        var src = src || [];  
        if(typeof src == "string") {  
            src = [src];  
        }  
        //获取head元素  
        var _doc = document.getElementsByTagName("head")[0];  
        var importObj = {};  
        if(src.length > 0) {  
            var curSrc = sPath + src[0];  
            //删除数组内第一个文件名  
            src.splice(0, 1);  
            var srctype = this.scrType(curSrc);  
            if(typeof this.scriptList[curSrc] === "undefined"   
                && typeof this.cssList[curSrc] === "undefined") {  
                        //如果没有加载过  
                if ("JS" == srctype) {                          
                    //加载js文件  
                    importObj = document.createElement("script");  
                    importObj.type = "text/javascript";  
                    importObj.language = "javascript";  
                    importObj.src = curSrc;                      
                    this.scriptList[curSrc] = 0;  
                } else if ("CSS" == srctype) {                          
                    //加载样式文件  
                    importObj = document.createElement("link");  
                    importObj.rel = "stylesheet";  
                    importObj.type = "text/css";  
                    importObj.href = curSrc;                      
                    this.cssList[curSrc] = 0;  
                }  
                //保存相关对象到importObj中  
                importObj.csrc = curSrc;    
                importObj.cstype = srctype;  
                importObj.self = this;  
                //加载成功事件  
                importObj.onload = importObj.onreadystatechange = function() {  
                    var csrc = this.csrc;                          
                    if(!this.readyState||this.readyState=='loaded'  
                        ||this.readyState=='complete'){                                  
                        var cst = this.cstype;  
                        var Self = this.self;         
                        //打上加载成功标志                            
                        if ("JS" == cst) {  
                            Self.scriptList[csrc] = "sucess";   
                            Self.LogInfo("import script " + csrc + " sucess.");  
                        } else if  ("CSS" == cst) {  
                            Self.cssList[csrc] = "sucess";  
                            Self.LogInfo("import css " + csrc + " sucess.");  
                        }  
                        this.onload=this.onreadystatechange=null;  
                        //继续加载后续文件,  
                        if(src.length > 0) {  
                            Self.Import(src, callBack, sPath);  
                        } else if(typeof callBack == "function") {  
                            callBack(true);  
                        }  
                        this.self = null;  
                    }  
                }  
                //导入错误的事件  
                importObj.onerror = function() {  
                    var Self = this.self;  
                    var csrc = this.csrc;   
                    var cst = this.cstype;        
                    //打上加载成功标志                        
                    if ("JS" == cst) {  
                        Self.scriptList[csrc] = "error";   
                        Self.LogInfo("import script " + csrc + " error.");                                           
                    } else if  ("CSS" == cst) {  
                        Self.cssList[csrc] = "error";  
                        Self.LogInfo("import css " + csrc + " error.");  
                    }  
                    //清除加载失败的文件  
                    _doc.removeChild(importObj);  
                    this.onerror = null;  
                    //继续加载后续文件,  
                    if(src.length > 0) {  
                        Self.Import(src, callBack, sPath);  
                    } else if(typeof callBack == "function") {  
                        //回调  
                        callBack(true);  
                    }  
                    this.self = null;  
                }  
                //添加加载文件到head中  
                _doc.appendChild(importObj);  
            } else {  
                if(src.length > 0) {  
                    this.Import(src, callBack, sPath);  
                } else if(typeof callBack == "function") {  
                    callBack(true);  
                }  
            }  
        } else if(typeof callBack == "function") {  
            callBack(true);  
        }                 
    }// Import  
} 
到此, 一个完整的动态加载对象已编写完成。 
请关注下一篇,将编写如何使用这个对象把更多的js导入到html页面中。