Dojo 的代码重用

前端之家收集整理的这篇文章主要介绍了Dojo 的代码重用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

引言

Dojo 工具包为程序员提供了很多功能丰富的控件,但是在实际应用中,很多时候程序员需要自定义控件来满足实际需求,如开发统一 UI 风格的控件库,开发具有通用逻辑组合的 Dojo 控件和更方便使用的 Dojo 控件库。自定义的控件可以在项目、团队中复用,从而可以充分提高开发效率和增加可维护性。


准备工作

在创建自定义控件之前需要就有以下知识:

  1. 了解 Dojo 和 Dojo 工具包

    请参考:http://dojotoolkit.org/reference-guide/quickstart/

  2. Dojo 开发环境的搭建

    下载 Dojo 工具包,http://dojotoolkit.org/download/

    调试工具安装,如 FireFox 浏览器下的 FireBug

  3. 开发和调试 Dojo 程序的基本步骤:

    使用 djConfig 加载 Dojo,请参考:http://dojotoolkit.org/reference-guide/djConfig.html#djconfig

    使用 dojo.require 加载 Dojo 控件,请参考:http://dojotoolkit.org/reference-guide/dojo/require.html#dojo-require

    申明和使用 Dojo 控件,请参考:http://dojotoolkit.org/reference-guide/dojo/index.html

    异常和调试,使用 try/catch 捕获异常,在 FireBug 中使用 console 进行日志记录和跟踪


创建自定义控件基础知识

在创建一个自定义控件时要使用到 Dojo 工具包的 dojo.provide、dojo.declare 函数和基础控件 Dijit._Templated、Dijit._widget,本节将介绍它们。

dojo.provide

dojo.provide 函数用于定义 Dojo 模块,dojo.provide 函数的定义方式为:

dojo.provide("模块名称");

Dojo 模块的名称在当前 Dojo 包下必须唯一,而且定义模块时模块名和模块的文件名称必须相同。

例如定义 my.module 模块,在 my/module.js 模块文件代码如下:


清单 1. 使用 dojo.provide 定义 Dojo 模块

<scripttype="text/javascript">
dojo.provide("my.module");

dojo.require("dojo.io.script");

my.module.name="mymodule";
</script>


dojo.declare

dojo.declare 函数使用类似面向对象的方式定义 JavaScript 类,但是它不是面向对象的。


表 1. dojo.declare 参数

参数名 数据类型 含义
类名 String 定义的类的名称
null

父类 null 没有父类
Object 一个父类
Object[] 多个父类


在 dojo.declare 中可以定义 constructor 函数用于申明类初始化时需要执行的代码,这很类似于 Java 类的构造方法

下面是一个使用 dojo.declare 定义类和使用定义类的简单实例:


清单 2. 使用 dojo.declare 定义类和使用类

dojo.declare("my.FirstSample",null,{
name:null,constructor:function(args){
dojo.safeMixin(this,args);
},setName:function(name){
this.name=name;
}
});
varsample1=newmy.FirstSample({name:"Jack"});//创建对象
console.log(sample1.name);
sample1.setName("Mark");//调用对象函数
console.log(sample1.name);


变量定义方式为,“变量名:变量值”,如 my.FirstSample 中定义的名称 name: null

函数定义方式为,“函数名:function( 参数 ){ 函数体 }”,如 my.FirstSample 中定义的函数

setName:function(name){
this.name=name;
}
使用 dojo.declare 定义继承

dojo.declare 可以定义当前类继承的父类,与面向对象不同的是可以是继承多个父类

在默认情况下,父类的构造函数会在子类的构造函数之前执行。

如果在子类中覆写了父类方法,可用 this.inherited(arguments) 来调用父类的同名方法


清单 3. 使用 dojo.declare 定义继承示例

dojo.declare("A",{
constructor:function(){console.debug("mixinginA");}
});
dojo.declare("B",{
constructor:function(){console.debug("mixinginB");},kind:"typeb",run:function(){
}
});
dojo.declare("C",[A,B,],{
constructor:function(){
console.debug("Ablizzardwith"+
this.kind+"MandMsand"
);
}
run:function(){
//callbaseclassrun
this.inherited();
//nowdosomethingelse
}
});


dijit._Templated

dijit._Templated 根据指定的 HTML 模板来创建 Widget 的 DOM 树,它可以作为创建 Widget 时的辅助。

指定 Widget 对应的 HTML 模板的方法有以下两种:


清单 4. 在 templateString 属性中申明 DOM 对象字符串

dojo.declare("MyWidget",[dijit._Widget,dijit._Templated],{
templateString:"<div>helloworld</div>"
});


清单 5. 在 templateString 属性中引用创建好的 HTML 文件

				
dojo.declare("MyWidget",{
templateString:dojo.cache("myNameSpace","templates/MyWidget.html"),});


在 HTML 文件中对象的唯一标示为 ID,在 Widget 的 HTML 模板中,可以用 dojoAttachPoint 属性来标示 DOM 对象,在 Widget 对象中可以直接用 this.${dojoAttachPoint} 来操作 DOM 对象,如清单 6 中的定义,可用 this.rootNode 来引用外层 div 对象,如:


清单 6. HTML 模板文件中的声明

<divdojoAttachPoint="rootNode">
<divdojoAttachPoint="chartNode">
</div>
<divdojoAttachPoint="legendHolder">
</div></div>


注意:定义 Widget 的 HTML 模板时根节点只能有一个,不要在根节点外写注释,在每行的结束时不能有’ > ’符,除非是最后一行。

dijit._ widget

dijit._widget 是所有 Widget 的基础类,在 Widget 的生命周期中重要的方法如下:

1 ) constructor 方法

创建 Widget 时首先执行的方法,此时你的 Widget 中变量还没有被赋值所以最好不要此时操作 Widget 的变量;

2 ) postMixInProperties 方法

在 DOM 对象创建前和 render 发生前执行,此时你的 Widget 的变量已经赋值,如果你想在控件的 DOM 对象创建前对 Widget 的变量进行处理,可以在子类中覆写这个方法

3 ) postCreate 方法

在 render 之后,但是子 Widget 还没有创建时执行。此时你可以操作当前 Widget 的 DOM 对象,所以大部分可以初始化操作可以在这处理,如绑定事件和设置 CSS 属性

注意:此时 Widget 可能还没有放到 DOM 树中,因此在此函数中不要处理 DOM 对象的大小。

4 ) startup 方法

在所有的子 Widget 创建完成和 parsing 完成后执行

5 ) destroy 方法

Widget 销毁前执行。

Widget 事件管理

Widget 可以对来自于 DOM 节点或对象的外部事件做出反应。这类事件可通过使用 Widget 的 connect 方法被手动连接,该方法如下(非常类似于 dojo.connect 方法):

connect:function(/*Object|null*/obj,/*String*/event,/*String|Function*/method);


如果在 Widget 生命周期内事件连接不需再要,可以调用 disconnect 方法来手动断开连接 .

Widget 的事件定制可以用 Widget 的 subscribe 方法来实现,改方法如下(类似于 dojo.subscribe 方法):

subscribe:function(/*String*/ topic,/*String|Function*/ method);

如果在 Widget 的生命周期内事件定制不需要,可以调用 unsubscribe 来取消定制。

注意 :

1)在自定义的 Widget 中,要进行初始化操作时覆写 postCreate 方法

2)在进行 Widget 销毁前处理时,最好不好覆盖父类的 destroy,因为 _widget 类的 destroy 方法自动销毁 Widget 及子 Widget 相关的资源,可以复写 uninitialize 方法来销毁需要手动销毁的资源,在 destroy 时会调用 uninitialize 方法

3)在使用 Widget 时,如果需要绑定事件或者定制事件时可以用 Widget 的 connect 和 subscribe 方法,在 Widget 销毁时会销毁相关的 connect 和 subscribe 句柄。如果需要手动销毁事件句柄可用 disconnect 和 unsubscribe 方法

4)对 Widget 的属性操作方法有:

  • 赋值:

    • 赋值方式一,在构造方法中赋值, 如:var fSmaple = new my.FirstSample({ name:"Jack"}); fSmaple 对象的 name 属性将在创建对象时被赋值;

    • 赋值方式二,创建完对象后赋值,attr("属性名",“属性值”),如:fSmaple.attr("name","Jack");dojo1.5 及以上版本推荐使用 widget.set('property','value');

  • 取值:

    • 获取 Widget 属性值用 attr("属性名"),如:fSmaple.attr("name");

    • Dojo1.5 及以上版本推荐使用 widget.get('property');

定义自定义控件步骤

根据第二节的介绍,本节将以 Radio Widget 为例介绍创建一个自定义控件的步骤。在 Dojo 库中有 dijit.form.RadioButton 这个控件,但是使用起来比较麻烦,下面是一个改进的自定义 RadioButton 的创建过程。

第一步,创建模板文件 RadioGroup.html

使用 dojoAttachPoint 属性定义 DOM 对象的唯一 ID,文件代码如下:


清单 7. RadioGroup 模板文件代码

		
<divdojoAttachPoint="myRatioNode"></div>


第二步,创建 RadioGroup.js 文件,创建步骤为:

1 引用 Dojo 工具包控件:


清单 8. 引用 Dojo 工具包控件

dojo.provide("health.RadioGroup");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dijit.form.CheckBox");

2 定义 health.RadioGroup 类

使用 dojo.declare 定义 health.RadioGroup 类,继承 dijit._Widget 和 dijit._Templated


清单 9. health.RadioGroup 定义语句

dojo.declare("health.RadioGroup",dijit._Templated]

3 绑定模板文件

使用 dojo.cache 绑定第一步中定义的模板文件


清单 10. 绑定模板文件

templateString:dojo.cache("health","templates/RadioGroup.html")|-------10--------20--------30--------40--------50--------60--------70--------80--------9||--------XMLerror:TheprevIoUslineislongerthanthemaxof90characters---------|


4 定义成员变量

定义变量时需要对变量进行初始化,如果无初始化值给变量赋值 null,格式如下:


清单 11. 定义成员变量

onChangeCallback:null,//当前Widget的成员变量
id:null,relativeChart:null,relativeChartGroup[]:null,name:"testName",//在定义变量时可以进行赋值

5 定义初始化函数

覆写构造函数 constructor(根据需要覆写);

覆写初始化函数 postCreate(根据需要覆写);

代码如下:
清单 12. 定义构造函数和初始化函数

constructor:function(params){//构造函数
this.relativeChartGroup=[];
},postMixInProperties:function(){
if(this.name==null){//在此时可以获取到变量的值
this.name="testName";
}
},postCreate:function(arguments){
console.debug("myRatioNode==",this.myRatioNode);
},


6 定义添加 Radio 选项函数

定义函数的格式为 :"函数名 : function( 参数 1,参数 2,参数 3,...)"。


清单 13. 添加 Radio 选项函数

addItem:function(value,lableText,checked){
if(checked==null){
checked=false;
}
console.debug("checked==",checked);
console.debug("value==",value);
console.debug("name==",this.name);

varself=this;
varradioOne=newdijit.form.RadioButton({
checked:checked,value:value,name:self.id,onChange:function(checked){
if(checked){
self.onChangeCallback(this.value);
}
}
});
this.domNode.appendChild(radioOne.domNode);
varlabel=document.createElement("label");
label.innerHTML=lableText;
this.domNode.appendChild(label);
}
});
注意:在函数中引用 widget 的变量或者调用其他函数时要用"this. 变量名 / 函数名"。

7 覆写 uninitialize 方法

在 uninitialize 中释放和销毁相关资源。


清单 14. Uninitialize 方法

uninitialize:function(arguments){
If(this.relativeChart)
this.relativeChart.destroy();
},
应用自定义的控件

第一步,引入自定义控件

在应用中引入自定义控件的方式有两种:

1) 将自定义的控件打包到 Dojo 包中

请参考:http://www.ibm.com/developerworks/cn/web/0912_shenjc_dojobuild/

2) 用 dojo.registerModulePath 注册自定义模块;
用 dojo.require 引用自定义控件。

例如,在第 3 节中创建的 Widget 可以用如下方式引用


清单 15. 引入自定义控件

dojo.registerModulePath("health","[path]/health");//注册自定义模块
dojo.require("health.RadioGroup");//引用自定义控件
第二步,使用自定义控件

1)用 new 创建自定义控件实例;

2)在创建实例时用“属性名:属性值”初始化实例变量;

3)在创建完自定义控件实例后调用对象的方法

使用自定义控件代码为:


清单 16. 创建自定义控件

varrateSelectRadio=newhealth.RadioGroup({
id:"rate_radio",relativeChart:chart
});
rateSelectRadio.addItem("weekly","周基准",true);
rateSelectRadio.addItem("monthly","月基准",false);
图 1:Radio Group 控件代码效果

应用自定义控件的创建方法的好处

在未使用自定义控件前,要绘制一个如图 1 效果的 Radio Group 代码如下:


清单 17. 未使用自定义控件时创建 Radio Group 的代码

varradioContainerNode=document.createElement("div");
varradioOne=newdijit.form.RadioButton({
checked:checked,value:"weekly",name:"rate_radio",onChange:function(checked){
if(checked){
doChangeRate(this.value);
}}});
this.domNode.appendChild(radioOne.domNode);
varlabel=document.createElement("label");
label.innerHTML="周基准";
radioContainerNode.appendChild(label);
varradioOne=newdijit.form.RadioButton({
checked:checked,value:"monthly",onChange:function(checked){
if(checked){
doChangeRate(this.value);
}}});
this.domNode.appendChild(radioOne.domNode);
varlabel=document.createElement("label");
label.innerHTML="月基准";
radioContainerNode.appendChild(label);
对比清单 16 和清单 17,可见使用自定义控件减少了开发工作。

结束语

使用自定义控件,可以充分复用 Dojo 代码,降低代码冗余,提高效率。建议大家在实际应用中,充分利用 Dojo 这一特征,写出干净漂亮的代码

转载自https://www.oschina.net/question/129540_28352

猜你在找的Dojo相关文章