jQuery Easyui Easyloader使用注意点总结

同步和异步
要理解Easyloader就必须对阻塞和非阻塞加载(对应同步和异步加载)有个大体的认识,所以这两个概念,必须钉在脑子里。

同步(阻塞)加载
我们平时最常使用是将"script"或者"style"标签直接写在html文档中的方式就是典型的同步加载方式。同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。

javascript之所以要同步执行,是因为脚本中可能有输出document内容、修改dom、重定向等行为,所以默认同步执行才是安全的。以前的一般建议是把"script"放在页面末尾"body"之前,这样尽可能减少这种阻塞行为,而先让页面展示出来。

异步(非阻塞)加载
 
function loadJs(url, callback) {   
    var done = false;   
    var script = document.createElement('script');   
    script.type = 'text/javascript';   
    script.language = 'javascript';   
    script.src = url;   
    //onreadystatechange和script.readyState属性事件是IE特有的,IE不支持script.onload   
    //firefox,chrome等其它浏览器支持只script.onload事件   
    script.onload = script.onreadystatechange = function() {   
        if(!done && (!script.readyState || script.readyState == 'loaded' || script.readyState == 'complete')) {   
            done = true;   
            script.onload = script.onreadystatechange = null;   
            if(callback) {   
                callback.call(script);   
            }   
        }   
    }   
    document.getElementsByTagName("head")[0].appendChild(script);   
}  
以上方式就是实现javascript异步加载的典型代码,用js创建一个script元素并插入到document中,这样就做到了非阻塞的下载js代码。此方法被称为"Script DOM Element"法,不要求js同源。Easyui的Easyloader便是用的这种方式实现异步加载的。

需要注意两点:

这种加载方式在加载执行完之前会阻止"onload"事件的触发,所以从某种意义上讲,这种方式实现的异步并不是完全的非阻塞;
异步加载并不一定能减少整个页面完全加载完所需的时间,有的时候按照模块加载恰恰是进行了多次http请求导致加载变慢,这就跟拷贝一个1G的大文件速度明显优于拷贝500个1M大小文件的道理是一样的。
Easyui的加载器
加载器的使用场景
你觉得一次性导入easyui的核心min Js和css太大,影响页面的相应速度,想先展示基础的文档结构给用户
你只用到easyui的其中几个组件,实在没必要导入所有组件的js和css文件
你想使用其中的一个组件,但是你又不知道这个组件依赖了那些组件
你甚至想把jQuery这样的基础库和自己写的js库,以提高基础文档结构展示给用户的速度
加载器的属性与事件
EasyLoader的API文档请参见:jQuery Easyui EasyLoader(加载器) API文档

加载器的使用方式
Easyui的加载器的使用方式有两种:

加载模块方式
 
//注意jquery,panelExtend,layoutExtend三个模块是我自定义的modul   
//因为jquery也是异步加载的,jquery的相关用法必须写在回调函数里。   
using(['jquery', 'parser', 'layout', 'menu', 'tabs', 'linkbutton', 'accordion', 'tree', 'panelExtend', 'layoutExtend'], function() {   
    alert('全部模块异步加载完成');   
    $(function(){   
        alert('全部文档装载完成');   
    });   
});  
加载单个文件方式
 
//加载单个文件方式,必须写绝对的url   
using("http://wwww.easyui.info/easyui/js/index2.js", function() {   
    alert('异步加载文件完成');   
});  
如何自定义模块
Easyui的作为认为一个模块应该至少包含一个js文件,至于css文件并不是必要的,所以我们定义模块的时候,不能仅仅将某个css文件定义为某个模块。

同时,对于模块扩展的写法也是很有考究的,很多同学想当然用下面的写法来扩展模块:

 
easyloader.modules = $.extand({},{   
    "mymodule1":{   
        js:'http://www.easyui.info/mymodule1.js',   
css:'http://www.easyui.info/mymodule1.css'},   
        "mymodule2":{   
        js:'http://www.easyui.info/mymodule2.js'        css:'http://www.easyui.info/mymodule2.css'  },   
        "mymodule3":{   
        js:'http://www.easyui.info/mymodule3.js'        css:'http://www.easyui.info/mymodule3.css'  },   
        .......   
},easyloader.modules);  
这样做遇到的第一个问题是,如果jquery库也是使用异步加载的话,那么$.extend函数是不能被使用的,当然了,这个还是比较容易理解的,而且大多数童鞋的jquery库是用同步加载的,并非异步,所以不用担心这个问题。

然而第二个问题你就不得不面对了,因为这样扩展模块,加载器根本识别不了你增加的模块,为什么呢?我们来看看加载器的源码:

 
(function(){   
    /**
        *定义一个对象modules,加载模块的时候,用的就是这个modules作为所有模块集合的  
        *modules究竟是什么,它只不过是一个引用罢了,对某段堆内存的引用,真正的对象是存储在堆内存中的  
        *如果在定义modules之后写有以下代码:  
        *var modulesCopy = modules;  
        *modulesCopy = new Object();  
        *modulesCopy.draggable.js = "唐老鸭";  
        *大家应该能能反应过来,modulesCopy.draggable.js重新设置值并不会影响到modules.draggable.js的值  
 
        *而jquery的easyloader.modules = $.extend({},modulesCopy,easyloader.modules);也是将easyloader.modules指向了另一段内存堆  
        *执行过这句代码后easyloader.modules和modules已经指向两个不同内存堆  
 
        *那么正确的应该如何写呢?  
        *easyloader.modules = $.extend(easyloader.modules,modulesCopy);这样写可以确保easyloader.modules和modules引用同一内存堆  
    **/    
    var modules = {   
        draggable:{   
            js:'jquery.draggable.js'   
        }   
        //此处省略诺干   
    };   
       
    var locales = {   
        'af':'easyui-lang-af.js'   
        //此处省略诺干   
    };   
       
    var queues = {};   
    /**
        此处省略诺干干干  
    **/  
    //是不是很蛋疼,用了一个没加var申明的easyloader,于是他就是全局变量了……   
    easyloader = {   
        modules:modules,//easyloader.modules跟modules指向同一堆内存   
        locales:locales,   
        base:'.',   
        theme:'default',   
        css:true,   
        locale:null,   
        timeout:2000,   
        load: function(name, callback){   
            //省略诺干   
        },   
           
        onProgress: function(name){},   
        onLoad: function(name){}   
    };   
  
    //省略诺干   
    window.using = easyloader.load;   
    //已经存在jq的话,先把parser组件加载了,继而解析整个页面   
    //很多组件还未加载,怎么能解析的呢?   
    //奥妙就在parser组件内部了,parser组件会自动检测页面包含的敏感easyui样式   
    //进而在使用easyloader将这个组件加载了   
    if (window.jQuery){   
        jQuery(function(){   
            easyloader.load('parser', function(){   
                jQuery.parser.parse();   
            });   
        });   
    }   
})();  
为了节省篇幅,没多大相关的代码我都省去了,注释部分我已经讲的比较清楚了,如果还不清楚的,要好好补一下javascript基础和jquery的extend函数的用法了

最终我们要想成功增加模块,必须按照以下写法才行:

 
$.extand(easyloader.modules,{   
    "mymodule1":{   
        js:'http://www.easyui.info/mymodule1.js',   
css:'http://www.easyui.info/mymodule1.css'},   
        "mymodule2":{   
        js:'http://www.easyui.info/mymodule2.js'        css:'http://www.easyui.info/mymodule2.css'  },   
        "mymodule3":{   
        js:'http://www.easyui.info/mymodule3.js'        css:'http://www.easyui.info/mymodule3.css'  }   
});   
推荐使用加载模块数组的方式
如果我们使用加载单个文件或者模块的方式,势必会牵扯到一个问题,如果文件或者模块间有依赖关系,我们就必须在回调函数里加载高级模块,如此一来回调函数可能就要嵌套很多层了。

而是用加载模块数组的方式,EasyLoder的内部实现了按照数组元素先后顺序同步加载,即,只要基础库写在数组前面就可以确保被同步优先加载。

对于Easyui自带组件之间的依赖,EasyLoder也有自身的算法,确保Easyui的基础类组件会被同步优先加载。如此一来,至少在代码的可读和可维护性上讲,优雅了很多。

最后的总结
异步加载的水还是比较深的,个人觉得easyui的核心文件也不是很大,没有特殊需求的同学就不要使用异步方式了,别把自己搞得焦头烂额,如果实在要使用而又没经验的,请细读本文,我想不会让你失望的。

要异步加载的演示?其实我的那个依旧待完善的API在线文档就是演示,它演示了异步方式如果是比同步方式更加的慢,典型的反面教材:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值