Ajax一统天下之Dojo整合篇


Posted in Javascript onMarch 24, 2007

随着Ajax应用越来越多,各种Ajax Library(Prototype),Ajax Framework(DWR),Ajax Toolkit(Dojo,YUI)也日渐丰富起来,有没有办法将这些结合起来呢?类似Spring的做法,当然我没法整出一个IoC的微内核将各种Ajax“粘合”起来,但是将这些Ajax可重用的组件加以整合应该是没有问题的,这样即可以避免重复发明轮子,还可以针对各种Ajax进行扬长避短,形成一套比较全面的Ajax解决方案。同时也增加了开发人员选择自己熟悉Ajax组件的灵活性。 
目前我们公司已经形成一套基于Ajax的完整的产品,封装了自己的Ajax前后台通讯机制以及提供了可重用的客户端组件,我尝试了一下将我们的产品与Dojo Toolkit进行整合。下面是我的做法,整合的是Dojo ComboBox Widget,它实际上是一个Auto Completion组件,类似Google Suggest。 
从Dojo提供的测试类test_ComboBox.html入手,加debugger进行跟踪调试,理清Dojo Widget的加载流程。 
经过跟踪调试,对Dojo的Widget有了一个大致的了解:首先是加载当前需要的JavaScript文件,然后对整个html页面进行解析。在页面上使用widget有三种方式:一种就是在html元素上添加一些dojo能解析的属性,如 
<select dojoType="combobox" style="width: 300px;" name="foo.bar1" autocomplete="false"  
        onValueChanged="setVal1"  
    >   
其中的dojoType,autocomplete, onValueChanged都是dojo能够识别的属性,这个有些类似typestry的做法。第二种就是使用DojoML的写法: 
<dojo:combobox style="width: 300px;" name="foo.bar1" autocomplete="false"  
        onValueChanged="setVal1"  
    />   
这种写法有些变态,跟jsp中的自定义标签基本就是一回事,只是把解析的过程从后台移到了前台来做,后来看到有些框架也这么干,也就没话说了。 
还有一种写法是使用javascript在页面加载完成之后,在指定的html元素创建widget: 
var combo;   
dojo.addOnLoad(init);   
function init(){   
combo = dojo.widget.createWidget("dojo:ComboBox", {name:"prog",autocomplete:false,dataUrl:"comboBoxData.js"}, dojo.byId("progCombo"));   
    }   
在对元素解析创建的时候同时利用dojo定义的combobox html模版以及css模版完成在页面中插入最终的combobox控件的目的。 
接下来看看Dojo ComboBox如何通过ajax与后台通讯,Dojo ComboBox提供了两种自动完成方式:一种是将所有的数据下载到前台缓存,然后在前台根据用户输入的数据从缓存中匹配出自动完成所需要的数据列表。另外一种就是根据用户每次输入的数据实时向后台发送请求获得要自动完成的数据,当然这个数据也会以用户输入的内容为key,以得到的数据为value进行缓存。对于两种方式,Dojo通过不同的DataProvider来实现(dojo.widget.incrementalComboBoxDataProvider和dojo.widget.basicComboBoxDataProvider),这一点非常精妙,让我非常佩服。而这两个类都是通过dojo.declare(“className”, “parentClassName”, constructor, declarationBody)这种方式来做的,这个也和我们以往的做法有别。总之就是比较精妙啦! 
Dojo向后台发送请求的过程封装在dojo.io.bind()这个方法中,而我们有自己的一套前后台通讯机制,因为必须想办法将dojo.io.bind()替换成我们的做法来达到最终整合的目的,因为Dojo ComboBox的数据交互都是封装在DataProvider里面的,因为我们只需要实现自己的DataProvider就可以搞定了,这样我们无须修改Dojo的源,而且还可以使用Dojo的继承机制,从已有的DataProvider集成复写掉我需要替换的方法,这让我有了写Java的感觉。 
dojo.declare(   
    "dojo.widget.incrementalDoradoComboBoxDataProvider",   
    dojo.widget.incrementalComboBoxDataProvider,   
    null,   
    {   
        //要替换的方法,使用自己的通讯机制   
        startSearch: function(/*String*/ searchStr, /*Function*/ callback){   
            if(this._inFlight){   
                // FIXME: implement backoff!   
            }   
            var cmd = getControl(this.searchUrl);   
            cmd.parameters().setValue("searchString", searchStr);   
            var _this = this;   
            EventManager.addDoradoEvent(cmd, "onSuccess", function(command){   
                    _this._inFlight = false;   
                    //convention:   
                    //1.the key must be "result"   
                    //2.the data format must be [["Alabama","AL"],["Alaska","AK"]] or [{"Alabama":"AL"},{"Alaska":"AK"}]   
                    var data = dj_eval(command.outParameters().getValue("result"));   
                    if(!dojo.lang.isArray(data)){   
                        var arrData = [];   
                        for(var key in data){   
                            arrData.push([data[key], key]);   
                        }   
                        data = arrData;   
                    }   
                    _this._addToCache(searchStr, data);   
                    callback(data);   
                }   
            );   
            cmd.execute();   
            this._inFlight = true;   
        }   
    }   
);   
通过上面的处理,就可以使用我们自己的前后台通讯机制来完成请求数据的目的。 
接下来就是生成我们的页面,添加dojo加载js的脚本: 
<script type="text/javascript" src="./dojo/dojo.js"></script>  
<script type="text/javascript">  
    dojo.require("dojo.widget.ComboBox");   
    // 注意这里有一个定位的问题,查找路径必须加"..",   
    // 因为dojo在查找DoradoComboBox.js的时候会从"/dojo"而不是"/"目录开始查找   
    // 最终使用xmlhttp加载的路径是/dojo/../adapter/dojo/widget/DoradoComboBox.js   
    dojo.setModulePrefix("adapter.dojo.widget","../adapter/dojo/widget");   
    dojo.require("adapter.dojo.widget.DoradoComboBox");   
</script>  
下面要加载的控件部分html: 
<input dojoType="ComboBox"    
                    dataUrl="cmdComboboxSearch"    
                    dataProviderClass = "dojo.widget.incrementalDoradoComboBoxDataProvider"    
                    style="width: 200px;"    
                    name="sample2"    
                    autocomplete="false"  
                    >   
这样我们的整合工作就完成了,对了还有文件的目录结构: 
Webapp 
|--adapter(存放所有用于整合的js文件) 
|------dojo 
|---------widget 
|-----------DoradoComboBox.js 
|--dojo(dojo的所有js文件) 
|------src 
|------dojo.js 
|--js(我们自己组件库的js文件) 
|--WEB-INF
结论 
通过扩展之后还是发现了不少问题: 
1、由于集成的两套东西都会在Object.prototype, Array.prototype, Function.prototype上加一些自己的东西,因此这样非常容易带来命名上的冲突,已经碰到这个问题。 
2、由于二者都会使用一些全局性的函数,变量等,这样也会存在潜在的冲突,不过目前还没有碰到。 
3、多套js库要同时加载,客户端的压力是不是大了些?性能可以接受吗?目前还没有测试不得而知。

Javascript 相关文章推荐
动态加载图片路径 保持JavaScript控件的相对独立性
Sep 06 Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
Nov 14 Javascript
javascript实现网页中涉及的简易运动(改变宽高、透明度、位置)
Nov 29 Javascript
利用React-router+Webpack快速构建react程序
Oct 27 Javascript
jQuery实现遍历XML节点和属性的方法示例
Apr 29 jQuery
vue-cli 3.x 修改dist路径的方法
Sep 19 Javascript
使用Vue实现移动端左滑删除效果附源码
May 16 Javascript
微信小程序实现拖拽功能
Sep 26 Javascript
Vue中keep-alive 实现后退不刷新并保持滚动位置
Mar 17 Javascript
JS写滑稽笑脸运动效果
May 28 Javascript
vue之封装多个组件调用同一接口的案例
Aug 11 Javascript
json.stringify()与json.parse()的区别以及用处
Jan 25 Javascript
dojo 之基础篇(三)之向服务器发送数据
Mar 24 #Javascript
dojo 之基础篇(二)之从服务器读取数据
Mar 24 #Javascript
dojo 之基础篇
Mar 24 #Javascript
jQuery使用手册之 事件处理
Mar 24 #Javascript
jQuery使用手册之三 CSS操作
Mar 24 #Javascript
jQuery使用手册之二 DOM操作
Mar 24 #Javascript
jQuery使用手册之一
Mar 24 #Javascript
You might like
php获取网站百度快照日期的方法
2015/07/29 PHP
PHP基于mssql扩展远程连接MSSQL的简单实现方法
2016/10/08 PHP
PHP实现网页内容html标签补全和过滤的方法小结【2种方法】
2017/04/27 PHP
PHP读取并输出XML文件数据的简单实现方法
2017/12/22 PHP
JSON语法五大要素图文介绍
2012/12/04 Javascript
jquery live()重复绑定的解决方法介绍
2014/01/03 Javascript
js showModalDialog弹出窗口实例详解
2014/01/07 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
2014/06/30 Javascript
jquery实现可横向和竖向展开的动态下滑菜单效果
2015/08/24 Javascript
Bootstrap每天必学之导航条
2015/11/27 Javascript
JS限制条件补全问题实例分析
2016/12/16 Javascript
深入理解Javascript中的观察者模式
2017/02/20 Javascript
Bootstrap下拉菜单更改为悬停(hover)触发的方法
2017/05/24 Javascript
详解vue在项目中使用百度地图
2019/03/26 Javascript
vue项目中使用vue-layer弹框插件的方法
2020/03/11 Javascript
[00:32]2018DOTA2亚洲邀请赛Mineski出场
2018/04/04 DOTA
python分析网页上所有超链接的方法
2015/05/08 Python
Django框架的中的setting.py文件说明详解
2018/10/15 Python
django 实现编写控制登录和访问权限控制的中间件方法
2019/01/15 Python
Python 70行代码实现简单算式计算器解析
2019/08/30 Python
python3操作注册表的方法(Url protocol)
2020/02/05 Python
用Python做一个久坐提醒小助手的示例代码
2020/02/10 Python
css3 按钮 利用css3实现超酷下载按钮
2013/03/18 HTML / CSS
CSS3实现可翻转的hover效果
2018/05/23 HTML / CSS
Jo Malone美国官网:祖玛珑香水
2017/03/27 全球购物
美国庭院家具购物网站:AlphaMarts
2019/04/10 全球购物
Groupon比利时官方网站:特卖和网上购物高达-70%
2019/08/09 全球购物
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
css animation配合SVG制作能量流动效果
2021/03/24 HTML / CSS
计算机专业推荐信范文
2013/11/27 职场文书
警校毕业生自我评价
2014/04/06 职场文书
机械专业技术员求职信
2014/06/14 职场文书
十佳青年事迹材料
2014/08/21 职场文书
普通党员个人整改措施
2014/10/27 职场文书
党的群众路线教育实践活动制度建设计划方案
2014/10/31 职场文书
舞蹈社团活动总结
2015/05/07 职场文书