前段时间的学习,试着分析了一下Calendar组件,却发现比较大,大致了解到组件的一般开发风格。我们在使用Calendar组件,两步,init();然后render();
init()所做事情有以下:
- 初始化组件所需参数;
- 将一般对组件的配置信息进行解析,一般设有默认配置信息,对于需要生成的id可以通过Dom.generateId()来得 到;
- initStyles() 日期组件的css 样式有专门的存放地方,initStyles就是初始化所需的className。
- initEvents() 初始化事件,有组件内部传递的事件,也有提供接口给调用者来订阅处理该事件;YAHOO提供了自定义事件对象的类CustomEvent通过这个初始化事件,并且指定方法订阅。
initEvents : function() { //将全局变量的长变量名 引用到 局部变量的短变量名。且将this赋值给局部变量,防止方法中的this的变换。 var defEvents = Calendar._EVENT_TYPES, CE = YAHOO.util.CustomEvent, cal = this; // To help with minification cal.beforeSelectEvent = new CE(defEvents.BEFORE_SELECT); cal.selectEvent = new CE(defEvents.SELECT); cal.beforeDeselectEvent = new CE(defEvents.BEFORE_DESELECT); cal.deselectEvent = new CE(defEvents.DESELECT); cal.changePageEvent = new CE(defEvents.CHANGE_PAGE); cal.beforeRenderEvent = new CE(defEvents.BEFORE_RENDER); cal.renderEvent = new CE(defEvents.RENDER); cal.beforeDestroyEvent = new CE(defEvents.BEFORE_DESTROY); cal.destroyEvent = new CE(defEvents.DESTROY); 。。。。//其他事件如上,下面就是订阅。 cal.renderNavEvent = new CE(defEvents.RENDER_NAV); cal.beforeSelectEvent.subscribe(cal.onBeforeSelect, this, true); cal.selectEvent.subscribe(cal.onSelect, this, true); cal.beforeDeselectEvent.subscribe(cal.onBeforeDeselect, this, true); 。。。//需要注意的是订阅的时候,传递this参数,指定本组件为事件的context }, - setupConfig()将默认配置信息初始化,如同initStyles()将样式class名转换为组件的变量。
- applyConfig()如果创建calendar的时候,有配置,则将配置信息覆盖在以前的默认配置上。
render()所作的事情很简单,就是创建日期组件所需的Element,在创建的时候,也许调用者想特殊处理一些信息,则将Event.fire(),调用者对事件subscribe来处理特殊;比如在日期创建之前想将页面做些其他改变。效果类似AOP面向切面。
render : function() {
//render之前的事件接口
this.beforeRenderEvent.fire();
var workingDate = DateMath.findMonthStart(this.cfg.getProperty(DEF_CFG.PAGEDATE.key));
this.resetRenderers();
this.cellDates.length = 0;
Event.purgeElement(this.oDomContainer, true);
var html = [];
html[html.length] = '<table cellSpacing="0" class="' + this.Style.CSS_CALENDAR + ' y' + (workingDate.getFullYear() + this.Locale.YEAR_OFFSET) +'" id="' + this.id + '">';
//这里就是浏览器会读取到的HTML代码。
html = this.renderHeader(html);
html = this.renderBody(workingDate, html);
html = this.renderFooter(html);
html[html.length] = '</table>';
this.oDomContainer.innerHTML = html.join("\n");
//内部事件的监听处理,比如日期组件的《》按钮的click事件
this.applyListeners();
this.cells = Dom.getElementsByClassName(this.Style.CSS_CELL, "td", this.id);
this.cfg.refireEvent(DEF_CFG.TITLE.key);
this.cfg.refireEvent(DEF_CFG.CLOSE.key);
this.cfg.refireEvent(DEF_CFG.IFRAME.key);
this.renderEvent.fire();
},
组件开发后还要添加上一句话:
YAHOO.register("calendar", YAHOO.widget.Calendar, {version: "2.8.0r4", build: "2449"});
用来方便YUI在YUILoader的时候的版本冲突控制。
仿造以上的开发风格,将网上的一个微调控件进行改装,符合YUI 组件的开发模式。效果如下:
![]()
升级为时间组件

进一步扩展日期组件:

开发中学到的小技巧:
setInterval的时候,需要将组件的this传递进去,可是因为setInterval是全局的函数,this为指到浏览器Dom。
var me=this;
this._interval = setInterval(function(){me.Run();},150);
使用这样的方法可以将调用函数的this变换,比较简单。
以上个人浅见,错误的地方欢迎大家指正。
876

被折叠的 条评论
为什么被折叠?



