大熊君JavaScript插件化開發------(實戰篇之DXJ UI ------ Tab)

一,開篇分析css

Hi,你們好!大熊君又和你們見面了,還記得前兩篇文章嗎。主要講述了以「jQuery的方式如何開發插件」,以及過程化設計與面向對象思想設計相結合的方式是html

如何設計一個插件的,兩種方式各有利弊取長補短,本系列文章是以學習爲導向的,具體場景你們本身定奪使用方式。那麼今天從這篇文章開始,咱們就以實例ajax

的方式帶着你們由淺入深的開發屬於本身的插件庫。嘿嘿嘿,廢話少說,進入正題。直接上實際效果圖:數組

  

  你們看到了吧,這是一個選項卡插件,在咱們平常作那種單頁應用("SPA")的時候或許會接觸到,就拿今天的例子來講吧,app

咱們作一個基於BS結構的系統,會有若干模塊組成,它們是構建系統的所有組成,經過這個插件咱們能夠有效地管理咱們模塊dom

的體驗形式以及用戶可交互性,下面就具體分析一下吧。ide

 

(二),實例分析源碼分析

  (1),首先肯定這個插件作什麼事。下面看一下插件的調用方式,以及配置參數說明。以下代碼:學習

 1 bigbear.ui.createTab($("#tab"),{
 2     buttonText : "添加模塊" ,
 3     result : [ 
 4         {
 5             text : "嚮導提示" ,
 6             url : "help.html" ,
 7             showClose : "0" ,
 8             status : "1"
 9         } ,
10         {
11             text : "學生信息" ,
12             url : "info.html" ,
13             showClose : "1" ,
14             status : "1"
15         } ,
16         {
17             text : "學生分類" ,
18             url : "category.html" ,
19             showClose : "1" ,
20             status : "1"
21         } ,
22         {
23             text : "大熊君{{bb}}" ,
24             url : "bb.html" ,
25             showClose : "1" ,
26             status : "1"
27         } ,
28         {
29             text : "Beta測試模塊" ,
30             url : "test.html" ,
31             showClose : "1" ,
32             status : "1"
33         }
34     ]
35 }) ;

 

「bigbear.ui.createTab」裏面包含兩個參數,第一個是dom節點對象,第二個是插件參數選項,"buttonText "表明「Tab「插件中,操做按鈕的文字描述。測試

」result「是一個數組,裏面包含的是選項卡項目的屬性,包括文字描述,點擊選項卡項目時作請求使用的url,」showClose「表明選項卡的選項是否顯示關閉按鈕。

」status「表明選項的狀態,默認爲打開狀態,可能會有關閉狀態,分別表示爲:1-打開,0-關閉。

 

(2),所涉的功能有哪些

經過可選參數,動態生成相關選項條目,以下來個例子:

  

 1 bigbear.ui.createTab($("#tab"),{
 2     buttonText : "添加模塊" ,
 3     result : [ 
 4         {
 5             text : "jQuery源碼分析" ,
 6             url : "help.html" ,
 7             showClose : "0" ,
 8             status : "1"
 9         } ,
10         {
11             text : "大熊君{{bb}}}" ,
12             url : "bb.html" ,
13             showClose : "1" ,
14             status : "1"
15         }
16     ]
17 }) ;

效果以下所示:

可自由添加以及刪除條目選項,以下效果所示:

  

 

上圖爲其中一種狀況,無模塊的時候,會提示信息。

 

 

這是第二種狀況,以前刪除的能夠恢復。

 

(三),完整代碼以供學習,本代碼已通過測試,包括目錄結構以及相關的文件。

  (1),html

    

 1 <body>
 2         <div class="dxj-ui-hd">
 3             大熊君{{bb}} - DXJ UI ------ Tab
 4         </div>
 5         <div class="dxj-ui-bd">
 6             <div id="tab">
 7                 <div class="title">
 8                     <div class="adder">
 9                         + 添加學生信息
10                     </div>
11                     <div class="items">
12                         <!--<div><span class="del">X</span>歡迎頁</div>
13                         <div><span class="del">X</span>用戶管理</div>
14                         <div><span class="del">X</span>Bigbear</div>-->
15                     </div>
16                 </div>
17                 <div class="console-panel">
18                 
19                 </div>
20                 <div class="content">
21                     <!--<div class="c">
22                     
23                         <div class="input-content"><span>姓名:</span><input type="text" /></div>
24                         <div class="input-content"><span>備註:</span><textarea></textarea></div>
25                     
26                     </div>    <div class="input-content"><input type="button" value="保存" /></div>
27                     -->
28                 </div>
29             </div>
30         </div>
31     </body>

 

(2),css文件代碼

  

  1 .dxj-ui-hd {
  2     padding:0px ;
  3     margin : 0 auto;
  4     margin-top:30px;
  5     width:780px;
  6     height:60px;
  7     line-height: 60px;
  8     background: #3385ff;
  9     color:#fff;
 10     font-family: "微軟雅黑" ;
 11     font-size: 28px;
 12     text-align: center;
 13     font-weight:bold;
 14 }
 15 .dxj-ui-bd {
 16     padding:0px ;
 17     margin : 0 auto;
 18     width:778px;
 19     padding-top : 30px ;
 20     padding-bottom : 30px ;
 21     overflow: hidden;
 22     border:1px solid #3385ff;
 23 }
 24 .dxj-ui-bd #tab {
 25     padding:0px ;
 26     margin : 0 auto;
 27     width:720px;
 28     overflow: hidden;
 29 }
 30 .dxj-ui-bd #tab .title {
 31     width:720px;
 32     overflow: hidden;
 33     border-bottom:2px solid #3385ff;
 34 }
 35 .dxj-ui-bd #tab .title .adder {
 36     width:160px;
 37     height:32px;
 38     line-height: 32px;
 39     background: #DC143C;
 40     color:#fff;
 41     font-family: "微軟雅黑" ;
 42     font-size: 14px;
 43     text-align: center;
 44     font-weight:bold;
 45     float : left;
 46     cursor:pointer;
 47 }
 48 .dxj-ui-bd #tab .title .items {
 49     height:32px;
 50     margin-left:20px;
 51     width:540px;
 52     overflow: hidden;
 53     float : left;
 54 }
 55 .dxj-ui-bd #tab .title .items div {
 56     padding:0px;
 57     margin-left:10px;
 58     width:96px;
 59     height:32px;
 60     line-height: 32px;
 61     background: #3385ff;
 62     color:#fff;
 63     font-family: arial ;
 64     font-size: 12px;
 65     text-align: center;
 66     position:relative;
 67     float : left;
 68     cursor:pointer;
 69 }
 70 .dxj-ui-bd #tab .title .items div span.del {
 71     width:16px;
 72     height:16px;
 73     line-height: 16px;
 74     display:block;
 75     background: #DC143C;
 76     position:absolute;
 77     right:0 ;
 78     top:0;
 79     cursor:pointer;
 80 }
 81 .dxj-ui-bd #tab .content {
 82     width:716px;
 83     padding-top:30px;
 84     overflow: hidden;
 85     border:2px solid #3385ff;
 86     border-top:0px;
 87     min-height:130px;
 88     text-align:center;
 89 }
 90 .dxj-ui-bd #tab .content table {
 91     margin : 0 auto ;
 92 }
 93 .dxj-ui-bd #tab .content div.c {
 94     padding-top : 20px ;
 95     padding-left:20px;
 96     background:#eee;
 97     height:140px;
 98 }
 99 .dxj-ui-bd #tab .content div.c .input-content {
100     margin-top : 10px ;
101     font-family: arial ;
102     font-size: 12px;
103 }
104 .dxj-ui-bd #tab .console-panel {
105     width:716px;
106     padding-top:20px;
107     padding-bottom:20px;
108     overflow: hidden;
109     border:2px solid #3385ff;
110     border-top:0px;
111     border-bottom:2px solid #3385ff;
112     background:#fff;
113     display:none;
114 }
115 .active {
116     font-weight:bold ;
117 }

 

(3),Js代碼以下:

  

  1 $(function(){
  2     bigbear.ui.createTab($("#tab"),{
  3         buttonText : "添加模塊" ,
  4         result : [ 
  5             {
  6                 text : "嚮導提示" ,
  7                 url : "help.html" ,
  8                 showClose : "0" ,
  9                 status : "1"
 10             } ,
 11             {
 12                 text : "學生信息" ,
 13                 url : "info.html" ,
 14                 showClose : "1" ,
 15                 status : "1"
 16             } ,
 17             {
 18                 text : "學生分類" ,
 19                 url : "category.html" ,
 20                 showClose : "1" ,
 21                 status : "1"
 22             } ,
 23             {
 24                 text : "大熊君{{bb}}" ,
 25                 url : "bb.html" ,
 26                 showClose : "1" ,
 27                 status : "1"
 28             } ,
 29             {
 30                 text : "Beta測試模塊" ,
 31                 url : "test.html" ,
 32                 showClose : "1" ,
 33                 status : "1"
 34             }
 35         ]
 36     }) ;
 37 }) ;
 38 (function($){
 39     var win = window ;
 40     var bb = win.bigbear = win.bigbear || {
 41         ui : {}
 42     } ;
 43     var ui = bb.ui = {} ;
 44     var Tab = function(elem,opts){
 45         this.elem = elem ;
 46         this.opts = opts ;
 47     } ;
 48     var tabProto = Tab.prototype ;
 49     tabProto._deleteItem = function(item){
 50         var that = this ;
 51         this.getElem().find(".title .items div")
 52         .eq(item["index"])
 53         .fadeOut(function(){
 54             that._resetContent() ;
 55             that._updateStatus(item) ;
 56             that._triggerItem(item["index"] + 1) ;
 57             that.getElem().find(".title .adder").trigger("click") ;
 58         }) ;
 59     } ;
 60     tabProto._triggerItem = function(next){
 61         var nextStatus = this._getStatus(next) ;
 62         var items = this.getElem().find(".title .items div") ;
 63         next = items.eq(next) ;
 64         if(next.size() && "1" == nextStatus){ //後繼dom節點存在
 65             next.trigger("click") ;
 66         }
 67         else{
 68             items.eq(0).trigger("click") ;
 69         }
 70     } ;
 71     tabProto._getStatus = function(index){
 72         var status = "" ;
 73         $.each(this.getOpts()["result"],function(i,item){
 74             if(index == item["index"]){
 75                 status += item["status"] ;
 76                 return false ;
 77             }
 78         }) ;
 79         return status ;
 80     } ;
 81     tabProto._updateStatus = function(item){
 82         var status = item["status"] ;
 83         item["status"] = ("1" == status) ? "0" : "1" ;
 84     } ;
 85     tabProto.init = function(){
 86         var that = this ;
 87         this.getElem().find(".title .adder")
 88         .text("+" + this.getOpts()["buttonText"])
 89         .on("click",function(){
 90             that._toggleConsolePanel(function(){
 91                 var root = that.getElem().find(".console-panel").empty() ;
 92                 $.each(that.getOpts()["result"],function(i,item){
 93                     if("0" == item["status"]){
 94                         var elem = $("<div style='float:left';></div>")
 95                         .data("item",item)
 96                         .appendTo(root) ;
 97                         $("<input type='radio' name='addmod' />").appendTo(elem) ;
 98                         $("<span></span>").text(item["text"]).appendTo(elem) ;
 99                     }
100                 }) ;
101                 if(root.find("div").size()){
102                     $("<input type='button' value='添加模塊' style='margin-left:20px'/>")
103                     .on("click",function(){
104                         var data = root.find("input[type=radio]:checked").parent().data("item") ;
105                         that._updateStatus(data) ;
106                         that.getElem().find(".title .items div").eq(data["index"]).fadeIn().trigger("click") ;
107                         that.getElem().find(".title .adder").trigger("click") ;
108                     })
109                     .appendTo(root) ;
110                 }
111                 else{
112                     root.text("暫無任何可添加的項目!") ;
113                 }
114             }) ;
115         }) ;
116         $.each(this.getOpts()["result"],function(i,item){
117             item["index"] = i ;
118             that._render(item) ;
119         }) ;
120         this.getElem().find(".title .items div")
121         .eq(0)
122         .trigger("click") ; // 假定是必須有一項,不然插件意義就不大了!
123     } ;
124     tabProto._toggleConsolePanel = function(callback){
125         this.getElem().find(".console-panel").slideToggle(function(){
126             $.isFunction(callback) && callback() ;
127         }) ;
128     } ;
129     tabProto._resetContent = function(){
130         this.getElem().find(".content").html("") ;
131     } ;
132     tabProto._setContent = function(html){
133         this.getElem().find(".content").html(html) ;
134     } ;
135     tabProto._getContent = function(url){
136         return $.ajax({
137             url : url
138         }) ;
139     } ;
140     tabProto._render = function(data){
141         var that = this ;
142         var item = $("<div></div>")
143         .text(data["text"])
144         .on("click",function(){
145             that._setCurrent(data["index"]) ;
146             that._getContent(data["url"]).done(function(result){
147                 that._setContent(result) ;
148             })
149             .fail(function(){
150                 throw new Error("Net Error !") ;
151             });
152         })
153         .appendTo(this.getElem().find(".title .items")) ;
154         if("1" == data["showClose"]){
155             $("<span class='del'>X</span>")
156             .on("click",function(){
157                 if(win.confirm("是否刪除此項?")){
158                     that._deleteItem(data) ;
159                     return false ; // 阻止冒泡
160                 }
161             })
162             .appendTo(item) ;
163         } 
164     } ;
165     tabProto._setCurrent = function(index){
166         var items = this.getElem().find(".title .items div").removeClass("active") ;
167         items.eq(index).addClass("active") ;
168         var contents = this.getElem().find(".content .c").hide() ;
169         contents.eq(index).show() ;
170     } ;    
171     tabProto.getElem = function(){
172         return this.elem ;
173     } ;
174     tabProto.getOpts = function(){
175         return this.opts ;
176     } ;
177     ui.createTab = function(elem,opts){
178         var tab = new Tab(elem,opts) ;
179         tab.init() ;
180         return tab ;
181     } ;        
182 })(jQuery) ;

 

 

(四),最後總結

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

  (2),以類的方式來組織咱們的插件邏輯。

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

    (4),思考一下上面例子中,選項卡中的選項是否能夠獨立成單獨的類那?好比「Item」,那麼「Tab」類如何修改那?帶着問題去思考吧。。。

 

                   哈哈哈,本篇結束,未完待續,但願和你們多多交流夠溝通,共同進步。。。。。。呼呼呼……(*^__^*)                      

相關文章
相關標籤/搜索