1 前言
1.1 传统JS前台编程方式
传统的前台编程模式如下
可以看出,传统的前台编程方式是面向过程的,不便于扩展于重用。在一个复杂的BS项目中,如果能够把抽象出界面中的某些具备共性的区域,把他们的行为(包括界面元素,界面事件,以及数据)封装起来将大大前端的开发效率。
1.2 Dojo简介
Dojo是一个工具箱,其定义了如下三大模块
1) 各式各样的JS标准库方法
这些标准库方法包罗万象并考虑了浏览器兼容性以及性能,在dojo框架下建议使用这些库函数可以屏蔽浏览器的差异
2) 一应俱全的Web组件包括基本组件(dijit)以及扩展(dojox)
在web组件方面,可以把Dojo的Web组件看成一个前台标签,页面加载完毕后dojo将会调用dojo.parser模块的parse方法扫描但前页面中所有具备dojotype属性的DIV标签,把它们parse成对应的web组件。这得一提的是这些组件全部是基于面向对象的思想设计,非常便于扩展,用户在外部可以通过重定向基类的方法,注入自己的界面行为,或者干脆通过继承来重载,覆盖父类的方法定义自己的组件。
1.3 基本概念介绍
面向对象的思想已经深入人心。而Dojo的web组件也基于面向对象的思想,所以在进一步介绍web组件之前,需要介绍一下JS的面向对象特性。
1.3.1 闭包
闭包本质上就是数据与包含数据的作用域的结合体。请看下例
1.3.2 this关键字
例子1)
例子2-1)
例子2-2)
由于onchange事件可以看成select的属性,因此可以认为是select调用了onchange,所以事件响应代码中的this 就是该DOM节点
例子3)
这个例子比较明显,由于是a调用了a.b所以在函数中。this就是a对象
1.3.3 apply函数的使用
在JavaScript中,一个函数其实是一个对象,任何一个函数都有一个apply方法,
apply方法JScript参考中的说明:应用某一对象的一个方法,用另一个对象替换当前对象。apply([thisObj[,argArray]])
apply([thisObj[,argArray]])中的参数为数组集合。下面来看看apply的具体应用
从上面简单的例子可以看出,apply可以把当前的参数传递给另外一个函数的参数中,从而调用另一个函数的应用。
apply还有一个技巧在里面,就是用apply应用另一个函数(类)以后,当前的函数(类)就具备了另一个函数(类)的方法或者是属性,这也可以称之为“继承”。看下面示例。
1.3.4 基于apply的dojo.hitch
如果直接这么写obj.onclick=functiona(arguments1,arguments2){…..};
我们会发现在functiona中,this就是触发click事件的Dom节点了
所以在我们的组件代码中,经常出现如下代码this.connect(obj,‘click’,dojo.hitch(this,functiona,arguments1,arguments2));这样functiona中的this和组件代码中的this保持一致,也就可以访问组件类中的属性以及方法了
我们看一下dojo.hitch的代码会发现如下片断
return function(){ return scope[method].apply(scope,arguments || []); }; // Function,可见它正是利用了apply的特性实现了作用域的变更。
dojo.hitch参数表为,第一个参数为作用域,第二个参数为函数对象,从第三个参数起就是第二个参数所对应函数的参数表
1.3.5 前后台交互XmlHttpRequest
现代浏览器都支持XmlHttpRequest,XmlHttpRequest的调用都是异步的也就是说这样的调用都无需页面进行跳转的。dojo再其上封装了dojo.xhr类。dojo的web组件接受json(javascript object notion)数据。所以使用dojo组件无需考虑后台的具体实现,只要后台能够提供异步请求机制,并且能够返回Json即可。在BME R4版本中,基于structs2以及jsonlib开发了异步请求action机制,调用这些action,BMER4版本定义了如下函数
2 组件开发介绍
2.1 dojo.declare
dojo把与实现类声明和继承有关的大量细节都封装到一个方法中,这个方法就是dojo.declare,这个方法包括三个参数
dojo.declare(/*String*/className,//要创建的构造函数名称
/*Function|Function[]*/superCalss,//要继承的超类构造函数,如果是构造函数数组则是多重继承
/*Object*/ //对象中的参数定义)
2.2 一个简单的基于dojo开发的web组件----Hellow World
Html页面
这个例子中使用this.connect绑定dom事件一是这个方法不会破坏原来已有的事件方法,如果button原来已有click响应函数,则这个操作将会把dojo.hitch(this,this.alertHellow)这个函数的动作追加到原来的操作后面,同时在对象销毁的时候(页面跳转,刷新),凡是被connect的函数都会去绑定,可以防止IE的内存泄露。
这个例子中也使用了dojo.hitch,这个方法可以改变函数的作用域,如果不使用dojo.htich则alertHellow函数中的this指向这个按钮,如果通过dojo.hitch作用,则这个函数种的this 指向这个组件的实例。通过这个机制,可以完全实现组件内部界面操作的封装。
postCreate是父类dijit.layout.ContentPane的方法,通过执行this.inherited(arguments);,父类的代码会被执行。如果没有这个调用,父类的方法就被覆盖了。
2.3 HelloWord升级,支持数据传入的表单
点击test
这个方法中使用dojo.forEach遍历表单元素。在function(item)
{
}
中this指向的不是组件实例,所以之前用一个变量_this存储了this
2.4 总结
通过以上介绍,我们可以得出如下结论
1) Dojo是是一个纯Javascript库,后台只要提供相应的接口能够将数据以Json的格式输出给前台即可;
3) Dojo自身定义界面组件库,其组件代码采用了面向对象的思想,便于继承以及扩展;只要组件库丰富;
4) 当对前端界面联动需求较为复杂的时候,基于dojo的页面组件将是首选,因为其可以将界面中某一个具有共性的区域抽象出来,封装这一区域的界面行为以及数据,可以用搭积木的方式完成复杂页面的开发。