麻雀虽小五脏俱全 Dojo自定义控件应用


Posted in Javascript onSeptember 04, 2010

现在Javascript框架、控件库有很多,jQuery、Ext、prototype、MooTools、Dojo等等,这些都是在Google上搜索“javascript+framework”列在第一页的。其中,除了MooTools,其它的都有所了解,但只在项目中用过Ext和Dojo。但一直不太喜欢Ext,性能有问题,新的版本还收费了。

另外,Ext官方提供的例子都是用JavaScript来创建和初始化控件,一个JavaScript配套一个HTML来用,这样管理起来很混乱。而且官方例子是Best Practice,所以不太接受这种模式。Dojo在本人眼里是一个缺点和优点都很突出的家伙:

缺点:

1、文档非常之差;

2、CodeBase非常之大(优点乎,缺点乎?);

3、版本演进快,且每次版本演进,都有大量的API发生变化,还不够成熟。

优点:

1、是一个很优秀的控件开发框架;

2、完全体现了javascript面向对象的一面。

EXT和Dojo比起来,本人觉得EXT是一个控件库,而Dojo是一个框架。第一次接触Dojo,当时版本0.3.X,今天项目中又有需求想用Dojo,版本是1.3.1,对比0.3和1.3,发现核心的思路并没有太大变化,但出厂提供的控件却有翻天覆地的变化,不过已经先入为主的对它的控件有成见,导致现在也没有兴趣再去研究,还是讲讲如何拿Dojo做自定义的控件吧。Dojo很复杂,但我们可以简单的认为它分三层:

1、最底层的是核心API

核心API提供的方法简化了DOM、字符串、CSS、事件等相关的操作。核心API还实现了类似于Java的package概念和import机制,方便了代码组织和依赖管理。

2、基于核心API,创造了“控件生命周期”概念

这是Dojo的亮点,允许第三方以规范的方式开发控件。基于Dojo开发的控件具有很强的内聚性和面向对象的特性。

3、基于2所开发的各类控件

Dojo自己提供的控件也比较全了,只是由于历史原因,没有深入研究过。

Dojo的控件统称DIJIT,要写出Dojo版的Hello World控件,你需要了解的知识并不太多:

◆一个控件就是一个JS类;

◆所有的控件都继承自_Widget或其子类,_Widget类提供了控件的生命周期管理函数;

◆可以同时继承_Templated,继承该类,可以为控件绑定模板来描述控件的展示。
关于_Widget基类的介绍
1、生命周期方法
_Widget提供了一系列方法称为“生命周期方法”,Dojo框架在初始化一个控件的时候,会依次调用它们,我们的自定义控件,可以重写特定的方法来加入自己的初始化逻辑,方法调用顺序及说明:

preamble(/*Object*/ params, /*DOMNode*/node) 
//这是一个通常不会用到的方法,这个方法的返回值,作为constructor的输入参数param 
constructor(/*Object*/ params, /*DOMNode*/node) 
// 这个方法相当于java类的构造函数 
// 在这个类中执行初始化动作 
postscript(/*Object*/ params, /*DOMNode*/node) 
//实际的控件创建过程,依次调用如下方法(都可以被重写) 
_Widget.create(/*Object*/params, /*DOMNode*/node) 
_Widget.postMixInProperties( ) 
_Widget.buildRendering( ) 
_Widget.postCreate( ) 
//我用得最多的是postCreate方法,这个方法中,控件已经初始化完毕,界面上也已经显示出来了, 
//通常在这个方法中启动业务相关的处理

2、该类的几个重要属性(控件可以通过this访问)
◆id:控件被授予的唯一编号,如果用户不指定,则Dojo随机创建一个。
◆domNode:该控件在HTML中对应的DOM节点。
最基本的自定义控件示例:
js文件:./hello/world.js(以下涉及到文件名,都用相对路径,其中./代表和"Dojo,dijit,Dojox"同级目录)。
//声明自己输出的类名 
Dojo.provide("hello.world"); 
//声明自己依赖的类名Dojo.require("dijit._Widget"); 
Dojo.require("dijit._Templated"); 
//Dojo.declare定义控件类,第一个参数:类名,第二个参数:父类数组,第三个参数:类的prototype 
Dojo.declare("hello.world",[dijit._Widget,dijit._Templated], 
{ 
postCreate:function(){ 
this.domNode.innerHTML="hellow world"; 
} 
} 
);

该控件的行为极其简单,在postCreate方法中,将自己在HTML页面中对应的DOM节点的内容设置为hellow world。
<html> 
<head> 
<title>Hello World</title> 
<!-- 首先引入Dojo.js,modulePaths用来定义包含控件的js目录,类似于jsp的自定义tag引入的机制--> 
<script type="text/javascript" src="./Dojo/Dojo.js" djConfig="parseOnLoad:true,modulePaths:{hello:'../hello'}"></script> 
<script type="text/javascript"> 
Dojo.require("Dojo.parser"); 
Dojo.require("hello.world"); //引入自定义控件 
</script> 
</head> 
<body> 
<div DojoType="hello.world"> 
</div> 
</body> 
</html>

modulePaths的具体作用和用法,请google即可。接下来,我们将控件参数化,我们可以在写标签的时候,将名字作为参数传进去,然后控件显示HELLO XXX,首先将html文件改成:
<html> 
<head> 
<title>Hello World</title> 
<!-- 首先引入Dojo.js,modulePaths用来定义包含控件的js目录,类似于jsp的自定义tag引入的机制--> 
<script type="text/javascript" src="./Dojo/Dojo.js" djConfig="parseOnLoad:true,modulePaths:{hello:'../hello'}"> 
</script><script type="text/javascript"> 
Dojo.require("Dojo.parser"); 
Dojo.require("hello.world"); 
</script></head><body> 
<div DojoType="hello.world" yourName="jinxfei"></div> 
</body> 
</html>

大家注意到,我们在标签上增加了“yourName”属性,在控件中如何使用该属性呢?可以在construtctor方法中接收此属性的值,将值赋给控件类自身的变量,然后在postCreate中使用,JavaScript代码如下:
Dojo.provide("hello.world"); 
Dojo.require("dijit._Widget"); 
Dojo.require("dijit._Templated"); 
Dojo.declare("hello.world",[dijit._Widget,dijit._Templated], 
{ yourName:'world', 
constructor:function(params,node) 
{ 
this.yourName=params.yourName; 
}, 
postCreate:function() 
{ 
this.domNode.innerHTML="hellow "+this.yourName; 
} 
} 
);

接下来,我们将进一步增加控件进的复杂性,增加一个输入框,在这个输入框中输入文本的同时,动态更新hello XXX,这就要用到Dojo的事件绑定机制,最常用的模式为:Dojo.connect(node,event,obj,method);表示将obj的method方法作为domNode的event事件处理函数,例如:
Dojo.connect(inputText,"onkey",this,"updateHello");

这次先改控件,在postCreate的时候,动态增加一个输入框,并为输入框动态绑定事件:
Dojo.provide("hello.world"); 
Dojo.require("dijit._Widget"); 
Dojo.require("dijit._Templated"); 
Dojo.declare("hello.world",[dijit._Widget,dijit._Templated], 
{ yourName:'world', 
typeIn:null, 
echoDiv:null, 
constructor:function(params,node) 
{ this.yourName=params.yourName; 
}, 
postCreate:function(){ 
this.typeIn=document.createElement("input"); 
this.typeIn.type="text"; 
this.domNode.appendChild(this.typeIn); 
this.echoDiv=document.createElement("div"); 
this.domNode.appendChild(this.echoDiv); 
Dojo.connect(this.typeIn,"onkeyup",this,"updateHello");//动态绑定事件 
this.updateHello();//调用方法初始化一下,先显示一个空的hello 
} , 
updateHello:function() 
{ 
this.echoDiv.innerHTML="hello "+this.typeIn.value; 
} 
} 
);

而HTML文件中对控件的引用,不用做任何改变(严格来讲,你需要删除yourName="jinxfei"这个属性)。从这个稍微有一点点复杂的控件,我们已经可以看出Dojo的优势:真正的面向对象!控件管理范畴内的DOM元素,都可以放在类中作为属性来使用(直接用this.xxx引用),这样,避免了document.getElementByID()满天飞,控件是内聚的。响应事件的方法也是类的方法,免得在页面中声明大量的离散function,不好管理。
Javascript 相关文章推荐
js展开闭合效果演示代码
Jul 24 Javascript
Javascript之this关键字深入解析
Nov 12 Javascript
js锁屏解屏通过对$.ajax进行封装实现
Jul 31 Javascript
JavaScript中数组成员的添加、删除介绍
Dec 30 Javascript
vuejs2.0运用原生js实现简单的拖拽元素功能示例
Feb 24 Javascript
小发现之浅谈location.search与location.hash的问题
Jun 23 Javascript
本地搭建微信小程序服务器的实现方法
Oct 27 Javascript
微信小程序实现全局搜索代码高亮的示例
Mar 30 Javascript
JavaScript选择排序算法原理与实现方法示例
Aug 06 Javascript
详解vue-router传参的两种方式
Sep 10 Javascript
JS实现图片幻灯片效果代码实例
May 21 Javascript
vue 路由缓存 路由嵌套 路由守卫 监听物理返回操作
Aug 06 Javascript
JavaScrip单线程引擎工作原理分析
Sep 04 #Javascript
onsubmit阻止form表单提交与onclick的相关操作
Sep 03 #Javascript
判断浏览器的javascript版本的代码
Sep 03 #Javascript
Extjs中DisplayField的日期或者数字格式化扩展
Sep 03 #Javascript
JavaScript的类型简单说明
Sep 03 #Javascript
JavaScript类和继承 this属性使用说明
Sep 03 #Javascript
JavaScript类和继承 prototype属性
Sep 03 #Javascript
You might like
在smarty中调用php内置函数的方法
2013/02/07 PHP
PHP实现生成透明背景的PNG缩略图函数分享
2014/07/08 PHP
php轻松实现文件上传功能
2016/03/03 PHP
JavaScript中跨域调用Flash的方法
2014/08/11 Javascript
JavaScript中property和attribute的区别详细介绍
2015/03/03 Javascript
JavaScript中的setUTCDate()方法使用详解
2015/06/11 Javascript
关于RequireJS的简单介绍即使用方法
2016/10/20 Javascript
ActiveX控件的使用-js实现打印超市小票功能代码详解
2017/11/22 Javascript
jQuery实现简单QQ聊天框
2020/08/27 jQuery
Javascript生成器(Generator)的介绍与使用
2021/01/31 Javascript
python中的sort方法使用详解
2014/07/25 Python
Python基于scrapy采集数据时使用代理服务器的方法
2015/04/16 Python
python安装oracle扩展及数据库连接方法
2017/02/21 Python
Python 安装setuptools和pip工具操作方法(必看)
2017/05/22 Python
python 读取txt中每行数据,并且保存到excel中的实例
2018/04/29 Python
Python 一句话生成字母表的方法
2019/01/02 Python
python实现定时压缩指定文件夹发送邮件
2020/12/22 Python
简单了解python 邮件模块的使用方法
2019/07/24 Python
python字典的遍历3种方法详解
2019/08/10 Python
python类中super() 的使用解析
2019/12/19 Python
手把手教你进行Python虚拟环境配置教程
2020/02/03 Python
Keras自定义实现带masking的meanpooling层方式
2020/06/16 Python
基于Python实现全自动下载抖音视频
2020/11/06 Python
pandas按条件筛选数据的实现
2021/02/20 Python
AmazeUI图片轮播效果的示例代码
2020/08/20 HTML / CSS
保时捷设计:Porsche Design
2019/03/30 全球购物
毕业生求职自荐信怎么写
2014/01/08 职场文书
《在山的那边》教学反思
2014/02/23 职场文书
入党介绍人评语
2014/05/06 职场文书
舞蹈教育学专业自荐信
2014/06/15 职场文书
远程培训的心得体会
2014/09/01 职场文书
财务整改报告范文
2014/11/05 职场文书
大学生操行评语大全
2014/12/31 职场文书
新员工辞职信范文
2015/05/12 职场文书
MySQL数据库必备之条件查询语句
2021/10/15 MySQL
利用Python实现Picgo图床工具
2021/11/23 Python