簡單叨叨bootstrap按鈕無限層級下拉菜單的實現



0、寫在前面的話

最近看書都懈怠了,又正值新項目,雖說並不是忙得不可開交,好吧我老實交待,我就是偷懶了其實,博客也沒更。言歸正傳,對於前端的不熟悉現在確實是個讓我頭疼的事情,以至於一些功能要在網絡上漫天飛舞瘋狂嘗試才能做得出來,關鍵是特別費時間,確實得抽時間補補前端的基礎才是。這次要實現一個分類選擇,即圖片上傳之前,抓取所有的圖片分類,然后在上傳頁面做成下拉菜單欄進行選擇。效果如下圖,理論上要達到無限層級的下拉菜單:
 

1、bootstrap的按鈕下拉菜單欄

bootstrap是有直接可以使用的下拉菜單插件的:
 
如上圖,這個效果差不多就是我們想要的樣式了,可是該插件是不支持無限層級分支的,也就是說只有如上圖方式的主菜單“Java”和其子項。

2、無限層級的bootstrap按鈕下拉菜單欄

然而網友的力量是強大的,在bootstrap按鈕下拉菜單欄的基礎上,網友拓展實現了無限層級子菜單,參見:
enter image description here

可以看到這個效果絕對是非常棒了,that's what I want!

說動手就動手,通過作者給的demo可以看到:
<li class="offset-left dropdown"> 
    <a href="#" class="dropdown-toggle">Dropdown...</a>
    <ul class="dropdown-menu">
        <li><a href="#">Secondary link</a></li>
        <li><a href="#">Something else here</a></li>
        <li><a href="#">Something else here</a></li>
        <li class="divider"></li>
        <li><a href="#">Another link</a></li>
    </ul>
</li>

凡是有子菜單延伸的條目,由普通的<li><a></a></li>變成如上形式即可。

3、前后端交互,前端數據的展示

3.1 struts標簽的失敗和啟示

前端頁面使用的JSP,項目使用了Struts,所以前端是可以直接使用struts的標簽的。也就是說,列表實體類可以直接通過struts抓取其中的屬性List,再通過<s:iterator>,如<s:iterator value="category.childCategoryList">,然后通過if else判定,如果沒有子類,則設定其樣式形為 <li><a></a></li>,如果有子類,則設定其樣式形為<li class="offset-left dropdown"><a href="#" class="dropdown-toggle">MenuName</a><ul class="dropdown-menu"> <li><a></a></li> </ul></li>

然而問題在於,每當子節點存在下一層子節點,我又必須增加一層if else判定,假如規定子分類最多4層,那么我的if判定也就寫4層好了,可是我們這個是理論上無限層級,假如用戶就是不斷建立分類細化,那怎么辦?顯然,這種方式是不合理的,而struts標簽頁沒有其他更好的方式來解決這種問題。

這種失敗在於數據的 局限性數據應該是后台處理好之后傳給前端,僅由前端來展示即可,而如上struts是將數據一股腦丟到前台,由前端來篩選組合處理,再進行展示,麻煩不言而喻。所以實際上應該將數據處理好,固化后再給前端解析使用。一旦數據結構固化,前端通過分析該數據,也就知道怎么做了。現在一般是使用Json,所以在我自己的這個例子中,我將后端的分類和子分類之間的關系,在后端轉換成json,傳遞給了前端,json結構如下:
[
  {
    "children": [
      {
        "children": [
          {
            "children": [],
            "id": 10,
            "text": "公司"
          },
          {
            "children": [],
            "id": 11,
            "text": "兼職"
          }
        ],
        "id": 3,
        "text": "工作"
      },
      {
        "children": [],
        "id": 4,
        "text": "生活"
      },
      {
        "children": [],
        "id": 5,
        "text": "個人"
      }
    ],
    "id": 2,
    "text": "日常"
  },
  {
    "children": [],
    "id": 6,
    "text": "高清大圖"
  },
  {
    "children": [
      {
        "children": [],
        "id": 8,
        "text": "修改"
      },
      {
        "children": [],
        "id": 9,
        "text": "測試回調"
      }
    ],
    "id": 7,
    "text": "測試"
  }
]

3.2 遞歸生成html

有了數據,只需要通過數據解析,然后組成相關的html代碼即可。如上的json結構,可以看到只要有chidren屬性不為空,那么我們就可以在該部分生成子菜單形式的樣式,否則使用普通的樣式。這里就要用到遞歸了,因為是無限層級,否則使用if判定則又和struts一樣進入了死胡同。

菜單部分的html是通過數據和算法生成的,不是固定的,需要提醒一下。則正常時空空如也:
<td>分類<b>*</b><br/>
    <div class="btn-group">
        <button id="categoryButton" idx="0" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" style="width:215px">
            請選擇圖片分類<span class="caret"></span>
        </button>
        <!--圖片分類的下拉菜單列表,通過js加載數據-->
        <ul id="categories" class="dropdown-menu" role="menu">
            <!--loading data in here-->
        </ul>
    </div>
</td>

后端給前端傳遞的json數據,變量名這里為categories,即如下的var data,那么接下來通過一個遞歸方法:
var glb_str = "";
function createCategoryTree(data) {
    var flag;
    for (var i = 0; i < data.length; i++) {
        var nodeText = data[i]['text'];
        var nodeId = data[i]['id'];
        var children = data[i]['children'];
        //若有子分類,則遍歷子分類
        if(children.length > 0) {
            flag = true;
            glb_str += "<li class='offset-right dropdown'><a class='category' " + "id=" + nodeId + " href='#'>" + nodeText + "...</a><ul class='dropdown-menu'>"
            createCategoryTree(children);
        } else {
            //若沒有子分類
            flag = false;
            glb_str += "<li><a class='category' " + "id=" + nodeId + " href='#'>" + nodeText + "</a>";
        }

        if (flag) {
            glb_str += "</ul></li>"
        } else {
            glb_str += "</li>";
        }
    }
    return glb_str;
}
 
//以上為方法定義,該處為調用
var data = ${categories};
var result = createCategoryTree(data);
$("#categories").append(result);

加載完成的頁面,可以看到,頁面源碼中已經有列表的html代碼了:
 

4、參考鏈接


趕時間,寫得潦草了些,就這樣吧~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM