當前位置:才華齋>設計>網頁設計>

JavaScript外掛化開發方式

網頁設計 閱讀(3.08W)

一,開篇分析

JavaScript外掛化開發方式

今天這篇文章我們說點什麼那?嘿嘿嘿。我們接著上篇文章對不足的地方進行重構,以深入淺出的方式來逐步分析,讓大家有一個循序漸進提高的過程。廢話少說,進入正題。讓我們先來回顧一下之前的

Js部分的程式碼,如下:

複製程式碼 程式碼如下:

function ItemSelector(elem,opts){

= elem ;

= opts ;

} ;

var ISProto = otype ;

lem = function(){

return ;

} ;

pts = function(){

return ;

} ;

/* data manip*/

ISProto._setCurrent = function(current){

pts()["current"] = current ;

} ;

urrentValue = function(current){

return pts()["current"] ;

} ;

/* data manip*/

= function(){

var that = this ;

pts()["current"] = null ; // 資料遊標

this._setItemValue(pts()["currentText"]) ;

var itemsElem = lem()("ent s") ;

lem()("e div")("click",function(){

le() ;

}) ;

lem()("e span")("click",function(){

le() ;

}) ;

$(pts()["items"],function(i,item){

item["id"] = (new Date()ime())ring() ;

that._render(item) ;

}) ;

} ;

ISProto._setItemValue = function(value){

lem()("e div")(value)

} ;

ISProto._render = function(item){

var that = this ;

var itemElem = $("

")

(item["text"])

("id",item["id"]) ;

if("0" == item["disabled"]){

("click",function(){

var onChange = pts()["change"] ;

lem()("ent s")() ;

that._setItemValue(item["text"]) ;

that._setCurrent(item) ;

onChange && onChange(item) ;

})

eover(function(){

$(this)lass("item-hover") ;

})

eout(function(){

$(this)veClass("item-hover") ;

}) ;

}

else{

("color","#ccc")("click",function(){

lem()("ent s")() ;

that._setItemValue(item["text"]) ;

}) ;

}

ndTo(lem()("ent s")) ;

} ;

效果如下圖所示:

a)------非可操作狀態

b)------可操作狀態

(二),開啟思路,進行重構

大家從程式碼不難看出,已經通過“Js”中的語法特性,以面向物件的方式進行了有效的組織,比鬆散的過程化形式的組織方式好多了,但是仍然會發現有很多不足的地方。

(1),裡面重複程式碼太多

(2),職責劃分不清晰

(3),流程梳理不健全

我們基於以上幾點進行有效的重構,我們首先要梳理一下這個元件的需求,功能點如下:

(1),初始化配置元件

複製程式碼 程式碼如下:

$(function(){

var itemSelector = new ItemSelector($("#item-selector"),{

currentText : "Please Choose Item" ,

items : [

{

text : "JavaScript" ,

value : "js" ,

disabled : "1"

} ,

{

text : "Css" ,

value : "css" ,

disabled : "0"

} ,

{

text : "Html" ,

value : "html" ,

disabled : "0"

}

] ,

}) ;

() ;

}) ;

這塊程式碼很清晰,不需要做任何修改,但是大家可以基於以上配置擴充套件功能,比如增加配置項“mode”支援多種選項方式。如:“checkbox勾選模式”。

接下來是要完成初始化邏輯,如下:

複製程式碼 程式碼如下:

= function(){

var that = this ;

pts()["current"] = null ; // 資料遊標

this._setItemValue(pts()["currentText"]) ;

var itemsElem = lem()("ent s") ;

lem()("e div")("click",function(){

le() ;

}) ;

lem()("e span")("click",function(){

le() ;

}) ;

$(pts()["items"],function(i,item){

item["id"] = (new Date()ime())ring() ;

that._render(item) ;

}) ;

} ;

這段程式碼問題很多,職責不明確,初始化邏輯包含了功能點的細節實現。

再繼續看渲染部分程式碼:

複製程式碼 程式碼如下:

ISProto._render = function(item){

var that = this ;

var itemElem = $("

")

(item["text"])

("id",item["id"]) ;

if("0" == item["disabled"]){

("click",function(){

var onChange = pts()["change"] ;

lem()("ent s")() ;

that._setItemValue(item["text"]) ;

that._setCurrent(item) ;

onChange && onChange(item) ;

})

eover(function(){

$(this)lass("item-hover") ;

})

eout(function(){

$(this)veClass("item-hover") ;

}) ;

}

else{

("color","#ccc")("click",function(){

lem()("ent s")() ;

that._setItemValue(item["text"]) ;

}) ;

}

ndTo(lem()("ent s")) ;

} ;

問題很明顯,發現了重複性的操作,應該進行合理的'抽象,已達到複用的目的。

整個組建的流程包括初始化,渲染(事件繫結),還有就是相關的資料操作方法以及dom操作的輔助方法。

綜上所述,經過簡單的梳理後,我們應該建立起功能的操作目的以及流程主線的任務分配,各負其責。

所以我們重構的目的很明確了,對!就是進行功能點的抽象,友好的職責劃分,那麼我們如何實現那?

第一步,建立流程功能方法:(方法介面)

複製程式碼 程式碼如下:

= function(){

// put you code here !

} ;

ISProto._render = function(){

// put you code here !

} ;

第二部,建立抽象後的方法介面:

複製程式碼 程式碼如下:

ISProto._fnItemSelectorDelegateHandler = function(){

// put you code here !

} ;

ISProto._fnTriggerHandler = function(){

// put you code here !

} ;

ISProto._addOrRemoveClass = function(){

// put you code here !

} ;

第三步,建立資料操作介面:

複製程式碼 程式碼如下:

ISProto._setCurrent = function(){

// put you code here !

} ;

ISProto._getCurrent = function(){

// put you code here !

} ;

還有一些參照下面的完整原始碼,這裡只是說的思路。

(三),完整程式碼以供學習,本程式碼已經過測試

複製程式碼 程式碼如下:

function ItemSelector(elem,opts){

= elem ;

= opts ;

ent = -1 ; // 資料遊標

} ;

var ISProto = otype ;

/* getter api*/

lem = function(){

return ;

} ;

pts = function(){

return ;

} ;

ISProto._getCurrent = function(){

return ent ;

} ;

/* getter api*/

/* data manip*/

ISProto._setCurrent = function(current){

ent = current ;

} ;

ISProto._setItemText = function(text){

lem()("e div")(text) ;

} ;

/* data manip*/

/* on 2015 1/31 23:38 */

ISProto._fnTriggerHandler = function(index,text,value){

if(this._isDisabled(value)){

index = -1 ;

text = pts()["currentText"] ;

}

this._setItemText(text) ;

this._setCurrent(index) ;

lem()("ent s")() ;

} ;

ISProto._addOrRemoveClass = function(elem,className,addIs){

if(addIs){

lass(className) ;

}

else{

veClass(className) ;

}

} ;

ISProto._fnItemSelectorDelegateHandler = function(){

var that = this ;

lem()("click","[data-toggle]",function(){

lem()("ent s")le() ;

}) ;

} ;

ISProto._isDisabled = function(value){

return ("1" == value) ? true : false ;

} ;

/* on 2015 1/31 23:38 */

= function(){

var that = this ;

this._fnItemSelectorDelegateHandler() ;

$(pts()["items"],function(i,item){

item["index"] = i ;

that._render(item) ;

}) ;

this._fnTriggerHandler(this._getCurrent(),pts()["currentText"],"1") ;

} ;

ISProto._render = function(item){

var that = this ;

var itemElem = $("

")(item["text"])("id",item["index"]) ;

var activeClass = ("0" == item["disabled"]) " : "item-disabled-hover" ;

("click",function(){

that._fnTriggerHandler(item["index"],item["text"],item["disabled"]) ;

})

eover(function(){

that._addOrRemoveClass($(this),activeClass,true) ;

})

eout(function(){

that._addOrRemoveClass($(this),activeClass,false) ;

}) ;

ndTo(lem()("ent s")) ;

} ;

(四),最後總結

(1),面向物件的思考方式合理分析功能需求。

(2),以類的方式來組織我們的外掛邏輯。

(3),不斷重構上面的例項,如何進行合理的重構那?不要設計過度,要遊刃有餘,推薦的方式是過程化設計與面向物件思想設計相結合。

(4),下篇文章中會擴充套件相關功能,比如“mode”這個屬性,為"1"時支援checkbox多選模式,現在只是預設下拉模式。

看我本文,是不是要比上一篇程式碼優秀了很多呢,小夥伴們自己做專案也應該多想多做,儘量使自己的程式碼更加的合理。