再议构建前端UI组件的新思路

近日,看了玉伯写的《构建前端UI组件的新思路》一文,让我追忆起去年自己分享的一篇P文《随感协同开发的JS设计模式》,有几分共鸣……

话说去年支付宝新版收银台项目中,我就小试了一把这种组件编码模式,点滴心得,这里和大家做一个交流:

回顾一下之前说到的抽象类,对设计模式有所了解的同学可能会觉得有些眼熟,没错,初一看,觉得它很像一个抽象工厂,但是结合下面的基础类来看,你会发觉我并没有在各基础类中,重写getVessel,show,hide等方法,而是直接继承了抽象类中的这些方法。一定会有人不解为什么要这么做,无他,就因为他是JS,而非JAVA。一定的偶合度换来足够的灵活在我看来一点都不过分,更何况这个抽象类是必须确保绝对稳定的,他在成形后不允许被随意修改那是必须的。

  1. AP.widget.basic = new AP.Class({
  2.   setOptions:function(options){
  3.     //接口设置
  4.   },
  5.   initialize:function(targets,options){
  6.     //初始化方法,目的是建立targets子集元素和某方法的关联 
  7.   },
  8.   getVessel:function(target){
  9.     //获取满足target映射关系的容器 
  10.   },
  11.   bindEvents:function(target,vessel){
  12.     //这里绑定target的触发动作
  13.   },
  14.   action:function(){
  15.     //target绑定的事件触发的执行函数,包含你要执行的逻辑 
  16.   },
  17.   show:function(){
  18.     //显示容器 
  19.   },
  20.   hide:function(){
  21.     //隐藏容器 
  22.   },
  23.   setInterface:function(){
  24.     //设置各组件共用接口 
  25.   }
  26. })

通过这个抽象类,我把一个触点对象和一容器对象做了关联,通过action方法去实现他们之间最简单的交互行为。“最简单”,那么无非就是显示或者隐藏之类的操作了,所以我又定义了show,hide方法。很明显“最简单”的交互行为没办法满足100%的用户行为,所以我必须设置一个setInterface方法,在需要特殊交互效果的类中去添加效果类。最后避免大家使用时直接实例化这个抽象类,在action方法中提醒大家,如要实例化操作,请到特定的继承类中去重写action方法。

通过这个抽象类,我们可以继承出最基础的aPop,dropDown,xbox,xTab等组件…这些上篇p文中已经有提到,这里不多说,着重解释一下在这写基础类满足不了特殊需求时,我们该如何快速的进行个性化组件开发。

下面以xTab为例,我们可以用这个组件完成基础的多触点多容器之间的切换效果,但是如果在这基础上需要再加一些动画效果又该怎么办呢?先看看继承类tab的实现代码:

  1. AP.widget.xTab = AP.widget.basic.extend({
  2.   bindEvents:function(target,vessel){
  3.     E.on(target,this.options.eventType,this.action,target,this);
  4.     E.on(window,'load',this.oXtab,target,this);
  5.   },
  6.   action:function(e,target){
  7.     this.switchTab(e,target);
  8.   },
  9.   switchTab:function(e,target){
  10.     ...
  11.     for(i=0,len=tabs.length;i<len;i++){
  12.       var hash = tabs[i].href.split("#")[1];
  13.       var vessel = D.get(hash + 'Extend');
  14.       if(vessel){
  15.         this.hide(vessel);
  16.       }
  17.       D.removeClass(tabs[i].parentNode,'current');
  18.       if(target.href == tabs[i].href){
  19.         D.addClass(target.parentNode,'current');
  20.         if(vessel){
  21.           this.show(vessel);    
  22.         }
  23.         //设置各类应用接口
  24.         this.setInterface(target,vessel);
  25.       }
  26.       E.preventDefault(e);
  27.     } 
  28.   },
  29.   showTab: function(index){
  30.     ...
  31.   },
  32.   //初始化定位tab
  33.   oXtab:function(target,e){
  34.     ...
  35.   }
  36. });

可以发现我在show方法之后执行了setInterface方法,这里默认会调用抽象类中的同名方法,这个接口方法是为同类交互行添加附加的交互效果类而设的。打个比方:现在要处理一个slideTab的效果,那么我们只需要基于xTab做一个应用类的继承,覆盖setInterface方法,添加一个实现slide效果的动画类就ok了!

  1. AP.widget.animTab = AP.widget.xTab.extend({
  2.   setInterface:function(target,vessel){
  3.     this.parent(target,vessel);
  4.     this.anim(vessel);
  5.   },
  6.   anim:function(vessel){
  7.      ...
  8.   }
  9. });

说实在的,这是挺土的一种设计思路,不过可以让我们换一种角度去思考组件的编码模式,以上只是粗浅的一些应用尝试,精彩还会继续…waiting for you!

Tags: , ,

[RSS 2.0] [留下宝贵的意见]



过客留言 该主题有9条留言

小新

不错的分享…还是老鱼实在

2010年6月星期2 [ 12:07 ]

uidesigner

半年了,老大,你的出品也太慢了点吧!!!

2010年6月星期2 [ 12:27 ]

sofish

磊哥,我是来顶的… 哦哈哈。

2010年6月星期2 [ 12:37 ]

小新

这种思路倒是挺特别的,如果能保证抽象类稳定的话,还是很好的实践

2010年6月星期2 [ 13:28 ]

Shimu

磊哥,一连两篇~期待

2010年6月星期2 [ 15:45 ]

匿名

以前也有想过,但从未实践,这么看来确实不错

2010年6月星期3 [ 00:56 ]

匿名

虽然看不懂,帮顶

2010年6月星期3 [ 05:05 ]

elex

这个和抽象工厂有积分相似,不过确实灵活很多,可以尝试用用!!

2010年6月星期3 [ 11:32 ]

小小花

非常有意思的开发模式,所有的交互形式都包含期中了。

2010年7月星期3 [ 01:28 ]