近日,看了玉伯寫的《構建前端UI組件的新思路》一文,讓我追憶起去年自己分享的一篇P文《隨感協同開發的JS設計模式》 ,有幾分共鳴……
話說去年支付寶新版收銀台項目中,我就小試了一把這種組件編碼模式,點滴心得,這裡和大家做一個交流:
回顧一下之前說到的抽象類,對設計模式有所了解的同學可能會覺得有些眼熟,沒錯,初一看,覺得它很像一個抽象工廠,但是結合下面的基礎類來看,你會發覺我並沒有在各基礎類中,重寫getVessel,show,hide等方法,而是直接繼承了抽象類中的這些方法。一定會有人不解為什麼要這麼做,無他,就因為他是JS,而非JAVA。一定的偶合度換來足夠的靈活在我看來一點都不過分,更何況這個抽象類是必須確保絕對穩定的,他在成形後不允許被隨意修改那是必須的。
AP.widget.basic = new AP.Class({
setOptions:function(options){
//接口設置
},
initialize:function(targets,options){
//初始化方法,目的是建立targets子集元素和某方法的關聯
},
getVessel:function(target){
//獲取滿足target映射關系的容器
},
bindEvents:function(target,vessel){
//這裡綁定target的觸發動作
},
action:function(){
//target綁定的事件觸發的執行函數,包含你要執行的邏輯
},
show:function(){
//顯示容器
},
hide:function(){
//隱藏容器
},
setInterface:function(){
//設置各組件共用接口
}
})
通過這個抽象類,我把一個觸點對象和一容器對象做了關聯,通過action方法去實現他們之間最簡單的交互行為。“最簡單”,那麼無非就是顯示或者隱藏之類的操作了,所以我又定義了show,hide方法。很明顯“最簡單”的交互行為沒辦法滿足100%的用戶行為,所以我必須設置一個setInterface方法,在需要特殊交互效果的類中去添加效果類。最後避免大家使用時直接實例化這個抽象類,在action方法中提醒大家,如要實例化操作,請到特定的繼承類中去重寫action方法。
通過這個抽象類,我們可以繼承出最基礎的aPop,dropDown,xbox,xTab等組件…這些上篇p文中已經有提到,這裡不多說,著重解釋一下在這寫基礎類滿足不了特殊需求時,我們該如何快速的進行個性化組件開發。
下面以xTab為例,我們可以用這個組件完成基礎的多觸點多容器之間的切換效果,但是如果在這基礎上需要再加一些動畫效果又該怎麼辦呢?先看看繼承類tab的實現代碼:
AP.widget.xTab = AP.widget.basic.extend({
bindEvents:function(target,vessel){
E.on(target,this.options.eventType,this.action,target,this);
E.on(window,'load',this.oXtab,target,this);
},
action:function(e,target){
this.switchTab(e,target);
},
switchTab:function(e,target){
...
for(i=0,len=tabs.length;i<len;i++){
var hash = tabs[i].href.split("#")[1];
var vessel = D.get(hash + 'Extend');
if(vessel){
this.hide(vessel);
}
D.removeClass(tabs[i].parentNode,'current');
if(target.href == tabs[i].href){
D.addClass(target.parentNode,'current');
if(vessel){
this.show(vessel);
}
//設置各類應用接口
this.setInterface(target,vessel);
}
E.preventDefault(e);
}
},
showTab: function(index){
...
},
//初始化定位tab
oXtab:function(target,e){
...
}
});
可以發現我在show方法之後執行了setInterface方法,這裡默認會調用抽象類中的同名方法,這個接口方法是為同類交互行添加附加的交互效果類而設的。打個比方:現在要處理一個slideTab的效果,那麼我們只需要基於xTab做一個應用類的繼承,覆蓋setInterface方法,添加一個實現slide效果的動畫類就ok了!
AP.widget.animTab = AP.widget.xTab.extend({
setInterface:function(target,vessel){
this.parent(target,vessel);
this.anim(vessel);
},
anim:function(vessel){
...
}
});
說實在的,這是挺土的一種設計思路,不過可以讓我們換一種角度去思考組件的編碼模式,以上只是粗淺的一些應用嘗試,精彩還會繼續…waiting for you!
轉載:http://ued.alipay.com/2010/06/proposed-front-end-ui-components-and-then-build-a-new-train-of-thought/