您当前的位置: 首页 > 技术文章 > 前端开发

QWrap入门之apps种子应用

作者:licqi 时间:2011-08-11阅读数:人阅读
就像是一棵树有很多果实一样,QWrap也有很多apps,本文讲解种子应用。“种子”是沿用YUI3的说法,种子应用是解决模块加载问题的应用,包括:模块预加载、异步按需加载、模块应用。 apps果实篇之:种子 或许有些同学对异步加载模块不大熟悉,没关系,我们先感性的看一下这段代码 [html]<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>QW应用之一:seed_youa</title> <meta http-equiv="Content-Type" content="text/html; charset=GB2312" /> <script type="text/javascript" src="http://dev.qwrap.com/resource/js/apps/seed_youa.combo.js"></script> </head> <body> <div id="div1">div1-----<span class="content">时间</span></div> <div id="div2">div2-----<span class="content">时间</span></div> <input type=button value="点击后按需加载后并修改div1/div2" onclick="test()"/> <script type="text/javascript"> function test(){ QW.use('jQuery,YouaCore',function(){ $('#div1').css('color','red').find('>.content').html(new Date()+'');//这段代码用到了jquery用法 W('#div2').css('color','blue').query('.content').html(new Date().format('YYYY-MM-dd hh:mm:ss'));//这段代码用到了Youa版的QWrap }); } </script> </body> [/html] 1. 如果用户浏览此网页时,只加载了一个体积很小的seed_youa.combo.js这个js(其实就是seed_youa.js(http://dev.qwrap.com/resource/js/apps/seed_youa.js)),这个js经yui压缩后的大小为4K。 2. 当用户点击按钮时,按钮对应的js用到jQuery与YouaCore,点击后才会去加载那两个jQuery与YouaCore对应的js,之后才有运行效果。 3. 第二次点击按钮,由于前面已经加载过js,所以这次会直接运行按钮事件。 分析一下以上三步,分两种情况。 A. 对于只进行了第一步操作的用户,他们用seed_youa.js替代了jQuery与YouaCore两个js的流量(这是好处甲); B. 对于进行过第二步操作的用户,由于以上流量的节约,会让用户提前能够点击按钮(这是好处乙),点击后异步加载需要的js,加载完后事件才运行,即点击与运行存在一个时间差(这是坏处甲),并且三个js都用到了,相对于传统写法,http多了一个seed_youa.combo.js(这是坏处乙)。 另外,对于页面程序员来说,他在写按钮事件时,只需要知道自己的这段js用到了哪些模块,而不用关心这些模块是否已经加载(这是好处丙),不过,他引用模块的方式有了一些变化(少键入html代码,多键入js代码)。 好处甲、好处乙、好处丙、坏处甲、坏处乙,还有些没有分析到的好处与坏处,反正有利有弊。 那么,在什么情况下利大于弊、什么情况下弊大于利,而我们该如何兴利除弊? 如果这个页面的用户100%不会点击按钮,则几乎没坏处,只有好处甲、好处丙。 如果页面100%的用户会点击按钮,则需要权衡再权衡利弊再想办法。 好的,我们先暂且搁置这些细节,因为以上内容已足够让同学们对“异步按需加载”有了感性的认识。我们把提供这种异步按需加载的js叫种子(seed)。 我们看一下seed_youa.js,它是一个组合js(即前面一篇文章所说的B类apps:开发时可以是多个文件,但上线时会先合并后上线。) 它由三个js组成: [js]document.write('<script type="text/javascript" src="' + srcPath + 'core/core_base.js"></script>'); document.write('<script type="text/javascript" src="' + srcPath + 'core/module.h.js"></script>'); document.write('<script type="text/javascript" src="' + srcPath + 'apps/youa_modules_config.js"></script>')[/js] core/core_base.js是QWrap的主干js core/module.h.js是模块管理器,也是一个Helper,提供三个方法:addConfig、use、provide,代码参见:http://dev.qwrap.com/resource/js/core/module.h.js youa_modules_config.js是youa项目只所使用到的常用模块配置,通过addConfig进行模块配置,代码如下: [js]/*Lib Module*/ QW.ModuleH.addConfig({ YouaCore: { url: '//apps/core_dom_youa_lazy.combo.js', loadedChecker:function(){ return !!(QW.W); } }, Ajax: { url: '//components/ajax/ajax.youa.js', requires: 'YouaCore' }, Anim: { url: '//components/animation/anim.js', requires: 'YouaCore' }, Cookie: { url: '//components/cache/cache.js', requires: 'YouaCore' }, Storage: { url: '//components/cache/cache.js', requires: 'YouaCore' }, Drag: { url: '//components/drag/drag.js', requires: 'YouaCore' }, Editor: { url: '//components/editor/editor.js', requires: 'YouaCore,Panel' }, Panel: { url: '//components/panel/panel.js', requires: 'YouaCore' }, Suggest: { url: '//components/suggest/suggest.js', requires: 'YouaCore' }, "Switch": { url: '//components/switch/switch.js', requires: 'YouaCore' }, Tree: { url: '//components/tree/tree.js', requires: 'YouaCore' }, Valid: { url: '//components/valid/valid.js', requires: 'YouaCore' }, jQuery: { url: 'http://common.cnblogs.com/script/jquery.js', loadedChecker:function(){ return !!(window.jQuery && window.jQuery.fn); } } }); /*Logic Module*/ QW.ModuleH.addConfig({ "User": { url: '//global/userv3.js', requires: 'YouaCore', loadedChecker: function() { return !!window.topbar; } }, ShopMap: { url: '//sp/map/shopmap.js', requires: 'YouaCore' } }); [/js] 看到这个配置文件的同学也许会问:模块添加得越来越多会怎么办?为什么不像YUI一样,在各个模块的js里进行addConfig,而要集中起来addConfig? 不错,理论上是会越来越大,但是,实际上最大能大到多少?并且不一定是所有的模块配置都要放在这里面。在页面的js里也可以QW.addConfig('MyPageJs','//my.js')的。所谓的太大,只是个理论问题,不是个实际问题。 YUI在各个模块的js里进行add,有好处,也有坏处。 好处就是多了个沙箱机制,沙箱理论看起来很严谨,可以满足YUI的严谨性洁癖----其实我一直没有理解它对实用者都有啥好处。 而坏处,也有很多。例如: 1.  需要模块的代码来适应他的加载机制。----例如,jQuery也可以算是个模块,凭什么要让独立的jquery来改代码? 2.  假设我改了jQuery的代码来适应这loader,那是不是也损失了jQuery的原来的用法,即预加载模式用法(在HTML的Header里引用jquery.js,在页面直接用$('#id').show())。 3.  例如use('Editor',function(){})时,其实由于依赖关系,会按需加载YouaCore,Drag,Panel,Editor四个js,因为依赖关系是在各自的js里,理论上无法将四个请求合并成一个请求,也无法在请求editor.js时就并行请求drag.js。 4.  如果客户端缓存了js,我们更新Editor.js后,use('Editor',function(){})无法知道是否需要在editor.js后添加版本号。 5.  如果有复合模块,例如core_dom_youa_lazy.js其实是同时拥有很多小模块功能的一个js,那在drap.js里如何定义依赖? 而QWrap的“集中配置”方式,上面几条都不是什么问题。 对于第一条第二条,已经解决,即:addConfig时的loadedChecker参数。 例如,这样配置jQuery: [js]QW.ModuleH.addConfig({ jQuery: { url: 'http://common.cnblogs.com/script/jquery.js', loadedChecker:function(){ return !!(window.jQuery && window.jQuery.fn); } } });[/js] 这个jQuery引用的是博客园网站的,我们没有作任何修改。 如果页面已经预加载了jquery,运行QW.use('jQuery',function(){})也不会再次加载jquery.js。 当然,用户还可以保持习惯,用以前的预加载经典用法。 对于第三条合并请求与并行请求,QW目前还没做,不过,只需调整一下module.h.js里的某一段代码即可。在源代码里有说明: [js]function loadsJsInOrder() { //浏览器不能保证动态添加的ScriptElement会按顺序执行,所以人为来保证一下 //参见:http://www.stevesouders.com/blog/2009/04/27/loading-scripts-without-blocking/ //测试帮助:http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=3&jsdelay=0&n=1&t=1294649352 //todo: 目前没有充分利用部分浏览器的并行下载功能,可以改进。 //todo: 如果服务器端能combo,则可修改以下内容以适应。 var moduleI = loadingModules[0]; function loadedDone() { moduleI.loadStatus = 2; var cbs = moduleI.__callbacks; for (var i = 0; i < cbs.length; i++) { cbs[i](); } isLoading = false; loadsJsInOrder(); } if (!isLoading && moduleI) { //alert(moduleI.url); isLoading = true; loadingModules.splice(0, 1); var checker = moduleI.loadedChecker; if (checker && checker()) { //如果有loaderChecker,则用loaderChecker判断一下是否已经加载过 loadedDone(); } else { loadJs(moduleI.url.replace(/^///, QW.PATH), loadedDone); } } } [/js] 对于第四条缓存,由于是统一配置,所以只需在发布时,在配置文件的js后面加上对应js的md5码的前N位即可。 例如,线上的配置可能是: [js]Ajax: { url: '//components/ajax/ajax.youa.js?111111.js', requires: 'YouaCore' }, Anim: { url: '//components/animation/anim.js?222222.js', requires: 'YouaCore' }[/js]页面引用的种子,也是在后面加上它的md5码的前N位。 这样做的好处是:每次上线后,用户也只需下载有过修改的js。 对于第五条的复合模块问题,由于是统一配置,所以根本就不是问题。 说了seed_youa.js的这么多好处,当然还要说明一个限制:项目中需要有一个水平还过得去的js同学,来负责这个统一的模块配置文件。 关于module.h.js还有挺多内容要讲的,不过,绝大同学不用关心它的实现;关心他的实现的同学大多也看过NK行的YUI3种子,再看这个两百行的module.h.js,应该是小case,这里先略过。 小结一下,QWrap的这个种子应用是绿色版的,并且小巧、灵活,可以直接复制过去引用。不过需要注意一下你所放的路径,防止QW.PATH的值计算有误,或者强制改掉QW.PATH的值。 附:QWrap网址:http://www.qwrap.com 原文:http://www.cnblogs.com/jkisjk/archive/2011/04/15/qwrap_apps_seed_youa.html

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:licqi@yunshuaiweb.com

加载中~
如果您对我们的成果表示认同并且觉得对你有所帮助可以给我们捐赠。您的帮助是对我们最大的支持和动力!
捐赠我们
扫码支持 扫码支持
扫码捐赠,你说多少就多少
2
5
10
20
50
自定义
您当前余额:元
支付宝
微信
余额

打开支付宝扫一扫,即可进行扫码捐赠哦

打开微信扫一扫,即可进行扫码捐赠哦

打开QQ钱包扫一扫,即可进行扫码捐赠哦