首页 | 新闻 | 交流 | 问吧 | 文档 | 手册 | 下载 | 博客

使用dojo.declare进行组件化开发

作者:  时间: 2011-06-02

dojo是我目前认为最强大的JS框架。

更多信息请访问 http://dojotoolkit.org/

dojo.declare是一个dojo中声明类的方法。所有的dijit小部件都建立在dojo.declare的基础上,得益于dojo.declare的强大的功能,很容易进行组件开发。下面就一个弹出层组件来说明dojo.declare的使用。

值得一提的是dojox提供了jq.js,从现在开始如果你不熟悉dojo也没有关系,可以使用jQuery的语法进行编码了,仅仅需要在JS的头部引入jq.js

dojo.require("dojox.jq")

当然现在问题不是讨论这个。。

进行组件开发的时候我们最关心的问题是这个组件应该提供什么样的功能。。就比如弹出层组件,你可能需要可以拖动,可以resize,可以变成确认框,可以变成提示框,可以加载远程文件,可以嵌入iframe等等。。但是你深入的去考虑,这些不过是弹出层的附加功能而已,说到最底层弹出层就只是show一个对话框出来,点击关闭按钮可以隐藏或者移除。其他的功能都是在此基础上进行的扩展,想通了这一点我们就可以使用dojo.declare进行优雅的编码了。。

我们声明一个dialog的类

dojo.declare("Y.dialog.Base",null,{
			//弹出层内容的节点
			node:null,
			//是否是遮罩
			modal:false,
			//弹出层的模板文件
			template:'<div class="simple-dialog"><a class="close">x</a></div>',
			//关闭时触发的函数
			onclose:function(){
				
			},
			//初始化时默认执行的函数
			constructor:function(args){
				dojo.safeMixin(this,args);
				this.dialog=$(this.template).clone();
				this.close=this.dialog.find(".close");
				this.close.click(dojo.hitch(this,"_hide"));
				this.init();
			},
			init:function(){
				this.dialog.append($(this.node)).appendTo(document.body);
			},
			_show:function(){
				this.dialog.show();
			},
			_hide:function(){
				this.dialog.hide();
			}
		});
注意我之前引入了dojox的jq模块

在此说明dojo.declare的语法

//args1:声明的类的名称

//args2:该类继承的父类,由我们现在本身就是基类,所以并没有继承的类。该参数可以为数组

//args3:一些散列

我们要在基类的基础上增加可以远程装载页面的功能。首先我们声明的类要继承这个基类,这个可以调用父级的_show,_hide等方法。其次我们可以重写父类的init的方法

//扩展
		dojo.declare("Y.dialog.Ajax",Y.dialog.Base,{
			//远程装载的地址
			url:null,
			//加载完毕执行的函数
			onload:function(){
				
			},
			constructor:function(args){
				dojo.safeMixin(this,args);
			},
			//在这里我们重写了父级的init方法
			init:function(){
				var self=this;
				if(this.url){
					$.ajax({
						url:this.url,
						dataType:"html",
						success:function(data){
							self.dialog.append(data);
							if($.isFunction(self.onload)){
								self.onload();
							}
						}
					});
				}
				self.dialog.appendTo(document.body);
			}
		});

为什么要这样写代码?

最重要的其实是一个模块的思想。组件的每个部分都是模块,我只希望使用我需要的部分,这样的话就必须将代码之间的耦合降低。。说白了就是解耦!!

我们可以这样使用

var d=new Y.dialog.Base({
				node:"#cc"
});

需要远程加载的话可以这样调用

var e=new Y.dialog.Ajax({
				url:"demo.html",
				onload:function(){
					console.info("加载完毕!")
				}
});

按照这种思路,我们可以将所需要的功能依次加上。比如拖动,resize等! dojo.declare的强大之处还在于可以实现多继承~~

我们希望按钮可以自己定制,于是我们声明了下面的类

dojo.declare("Y.dialog.Button", Y.dialog.Base, {
                buttons: null,
                constructor: function(args){
                    dojo.safeMixin(this, args);
                    
                },
                _buildBtns: function(){
                    if (this.buttons) {
                        var buttonParent = $("<div/>").addClass("buttonParent");
                        $.each(this.buttons, function(key, value){
                            var button = $("<button/>").text(key).click(value);
                            buttonParent.append(button);
                        });
                        this.dialog.append(buttonParent);
                    }
                }
            })

我们修改Ajax的继承类

 dojo.declare("Y.dialog.Ajax", [Y.dialog.Base,Y.dialog.Button],{
//...
})

我们再次new一个Ajax的实例

 var e = new Y.dialog.Ajax({
                    url: "demo.html",
                    onload: function(){
                        console.info("加载完毕!");
                    },
					buttons:{
						'确定':function(){
							console.log("确定");
						},
						'取消':function(){
							console.log("取消");
						}
					}
                });

结果就是如下图所示

你可能会有所疑问。我可以通过call,apply等函数实现相关的功能,但是等到你代码上千行的时候,他们之间的关系你还能理得清吗?

优雅编码从现在开始。。。

本文仅是示例,高手看看就算了。。。