麻雀虽小五脏俱全 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实现兼容IE6与IE7的DIV高度
May 13 Javascript
关于jquery动态增减控件的一些想法和小插件
Aug 01 Javascript
仿新浪微博返回顶部的jquery实现代码
Oct 01 Javascript
纯css+js写的一个简单的tab标签页带样式
Jan 28 Javascript
jquery选择器使用详解
Apr 08 Javascript
JavaScript图像延迟加载库Echo.js
Apr 05 Javascript
Bootstrap文件上传组件之bootstrap fileinput
Nov 25 Javascript
微信小程序 检查接口状态实例详解
Jun 23 Javascript
vue中如何实现pdf文件预览的方法
Jul 12 Javascript
在Vue中使用axios请求拦截的实现方法
Oct 25 Javascript
深入解析Vue源码实例挂载与编译流程实现思路详解
May 05 Javascript
Vue+Bootstrap实现简易学生管理系统
Feb 09 Vue.js
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
php处理文件的小例子(解压缩,删除目录)
2013/02/03 PHP
PH P5.2至5.5、5.6的新增功能详解
2014/07/14 PHP
getimagesize获取图片尺寸实例
2014/11/15 PHP
详解如何在云服务器上部署Laravel
2017/06/30 PHP
深入理解 PHP7 中全新的 zval 容器和引用计数机制
2018/10/15 PHP
在laravel中使用with实现动态添加where条件
2019/10/10 PHP
php 使用 __call实现重载功能示例
2019/11/18 PHP
多浏览器兼容的获取元素和鼠标的位置的js代码
2009/12/15 Javascript
Javascript 实现TreeView CheckBox全选效果
2010/01/11 Javascript
javascript下判断一个元素是否存在的代码
2010/03/05 Javascript
Select标签下拉列表二级联动级联实例代码
2014/02/07 Javascript
jQuery Migrate 1.1.0 Released 注意事项
2014/06/14 Javascript
浅析JavaScript中的事件机制
2015/06/04 Javascript
你不知道的高性能JAVASCRIPT
2016/01/18 Javascript
requireJS使用指南
2016/04/27 Javascript
jQuery实现的鼠标经过时变宽的效果(附demo源码)
2016/04/28 Javascript
Angular学习笔记之集成三方UI框架、控件的示例
2018/03/23 Javascript
详解react阻止无效重渲染的多种方式
2018/12/11 Javascript
微信小程序实现搜索功能并跳转搜索结果页面
2019/05/18 Javascript
Vue 使用beforeEach实现登录状态检查功能
2019/10/31 Javascript
nuxt.js写项目时增加错误提示页面操作
2020/11/05 Javascript
MySQLdb ImportError: libmysqlclient.so.18解决方法
2014/08/21 Python
在Python中移动目录结构的方法
2016/01/31 Python
举例讲解Python设计模式编程中对抽象工厂模式的运用
2016/03/02 Python
利用Python在一个文件的头部插入数据的实例
2018/05/02 Python
python实现支付宝转账接口
2019/05/07 Python
如何使用Python实现斐波那契数列
2019/07/02 Python
Python实现查找数据库最接近的数据
2020/06/08 Python
python+pygame实现坦克大战小游戏的示例代码(可以自定义子弹速度)
2020/08/11 Python
Django怎么在admin后台注册数据库表
2020/11/14 Python
台湾生鲜宅配:大口市集
2017/10/14 全球购物
物业保安岗位职责
2014/07/02 职场文书
2015年毕业生自荐信范文
2015/03/24 职场文书
小学英语教学经验交流材料
2015/11/02 职场文书
读《皮囊》有感:理解是对他人的最大的善举
2019/11/14 职场文书
Element实现动态表格的示例代码
2021/08/02 Javascript