javascript控件开发教程之动态加载(1)

发布时间:2019-07-27编辑:脚本学堂
本文介绍了javascript控件开发教程中有关动态加载的方法,本节是javascript控件开发之动态加载的第一部分,有需要的朋友参考下。

随着前端应用越来越火,应用越来越复杂,不管是什么系统,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页面中。