本文將介紹自定義的bootstrap級聯下拉菜單,主要應用場合有省市級關聯菜單等等,那麼就先拿這個例子來講,當然其他場景的關聯菜單也同樣適用。說實話,封裝好一個通用的組件還是需要花費很多精力的和時間的,所謂通用,自然要考慮周全,歎!這次整理的Bootstrap關聯select,裡面也涉及到了很多jquery、ajax、springMVC等等知識點,可謂包羅萬象!
首先,請允許我代表該自定義組件做一番小小的介紹。
“hi,你好,我叫yunm.combox.js,主人給我起的名字,其實呢,挺俗的。我主要通過為select組件增加兩個自定義屬性來完成相應的數據加載,數據請求使用了ajax,後端數據處理使用了springMVC(當然其他方式也可以,只需要返回對應的json數據即可),使用起來呢,就非常非常簡單了!”
一、界面效果
當然了,從界面上完全看不出來一個組件封裝的好壞,但至少,你感覺很簡潔漂亮,那麼好了,有了這層印象,你是否有興趣繼續看下去?我想答案是肯定的。
二、使用方法
①、procity.jsp
首先呢,在頁面上加載yunm.combox.js(稍候介紹,至於其他的bootstrap的css和js,不在本章介紹范圍內,略過),同時呢,創建兩個select,具體格式見如下:
<script type="text/javascript" src="${ctx}/components/yunm/yunm.combox.js"></script> <div class="form-group"> <div class="row"> <div class="col-md-6"> <select name="province_code" class="form-control combox" ref="city_select" refUrl="${ctx}/procity?pro_code={value}&city_code=HSLY"> </select> </div> <div class="col-md-6"> <select name="city_code" id="city_select" class="form-control"> </select> </div> </div> </div> <script type="text/javascript"> <!-- $(function() { if ($.fn.combox) { $("select.combox", $p).combox(); } }); //--> </script>
·兩個select組件,一個為province_code、一個為city_code。
·省級菜單上增加了兩個屬性。
ref指定關聯菜單為市級菜單city_select
refUrl指定菜單獲取數據的URL
pro_code作為獲取市級數據的關鍵因子
{value}呢,則為通配符,稍候在介紹組件的時候繼續講到
city_code=HSLY,主要用於選中指定的省市菜單,諸如上文中的(河南、洛陽),如果不選中,則city_code=為空
·class=”combox” 為該省級下拉框增加jquery選擇器
·頁面加載完畢後執行combox組件的關鍵方法,下面詳細介紹
②、yunm.combox.js
現在我們來看看關鍵的組件內容吧!
(function($) { var _onchange = function(event) { var $ref = $("#" + event.data.ref); if ($ref.size() == 0) return false; var refUrl = event.data.refUrl; var value = encodeURIComponent(event.data.$this.val()); YUNM.debug(value); $.ajax({ type : 'POST', dataType : "json", url : refUrl.replace("{value}", value), cache : false, data : {}, success : function(response) { $ref.empty(); addHtml(response, $ref); $ref.trigger("change").combox(); }, error : YUNM.ajaxError }); }; var addHtml = function(response, $this) { var json = YUNM.jsonEval(response); if (!json) return; var html = ''; $.each(json, function(i) { if (json[i]) { html += '<option value="' + json[i].value + '"'; if (json[i].selected) { html += ' selected="' + json[i].selected; } html += '">' + json[i].name + '</option>'; } }); $this.html(html); }; $.extend($.fn, { combox : function() { return this.each(function(i) { var $this = $(this); var value = $this.val() || ''; var ref = $this.attr("ref"); var refUrl = $this.attr("refUrl") || ""; if (refUrl) { refUrl = refUrl.replace("{value}", encodeURIComponent(value)); } if (refUrl) { $.ajax({ type : 'POST', dataType : "json", url : refUrl, cache : false, data : {}, success : function(response) { addHtml(response, $this); if (ref && $this.attr("refUrl")) { $this.unbind("change", _onchange).bind("change", { ref : ref, refUrl : $this.attr("refUrl"), $this : $this, }, _onchange).trigger("change"); } }, error : YUNM.ajaxError }); } }); } }); })(jQuery);
·通過$.extend($.fn, { combox : function() {為jquery增加一個叫combox的底層(可以查詢jquery幫助文檔)方法。
·通過(function($){_onchange、addHtml})(jQuery);為該組件在頁面初始加載時創建兩個方法onchange和addHtml,至於(function($) {})(jQuery);我想你如果不了解的話,趕緊百度吧!
·先來看combox 方法
獲取ref、refUrl,通過ajax向refUrl請求省級菜單數據,當獲取成功後,通過addHtml方法將json轉換後的option綁定到省級菜單select上
然後呢,為省級菜單select綁定change事件,傳遞的參數為ref(市級菜單)、refUrl(市級數據獲取的url)、$this(省級菜單,便於change事件獲取對應選中項,如效果圖中的河南)
通過trigger方法立即執行change事件,便於獲取對應的市級菜單內容。
·再來看_onchange方法,主要是點擊省級菜單時觸發,用於獲取市級菜單列表
refUrl,向服務端請求的URL
value,用於獲取省級菜單的選中項目,然後通過該value值獲取省級對應的市級菜單
$ref.empty();用於清空市級菜單
通過ajax繼續獲取市級菜單內容,然後通過addHtml方法添加到市級菜單中。
·addHtml方法
通過jsonEval方法對服務端傳遞回來的數據進行eval(eval('(' + data + ')'),如有不懂,可百度)方法處理,否則會出錯。
$.each(json, function(i) {遍歷json,通過jquery創建option對象,然後加入到select中。
③、ProcityController
前端介紹完了,我們回到後端進行介紹,當然了,你也可以忽略本節,因為不是所用的關聯數據都通過springMVC這種方法獲取,那麼先預覽一下代碼吧!
package com.honzh.spring.controller; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import com.honzh.biz.database.entity.City; import com.honzh.biz.database.entity.Option; import com.honzh.biz.database.entity.Provincial; import com.honzh.common.util.JsonUtil; import com.honzh.spring.service.CityService; import com.honzh.spring.service.ProvincialService; @Controller @RequestMapping(value = "/procity") public class ProcityController extends BaseController { private static Logger logger = Logger.getLogger(ProcityController.class); /** * 當傳遞city_code,則表明下拉框要被選中,否則不選中 */ @RequestMapping("") public void index(@RequestParam(value = "city_code", required = false) String city_code, @RequestParam(value = "pro_code", required = false) String pro_code, HttpServletResponse response) { try { logger.debug("獲取所在地區" + city_code + ", 省" + pro_code); // 如果pro_code為””,則表明要獲取城市菜單,否則獲取市級菜單 if (!pro_code.equals("")) { Integer pro_id = ProvincialService.getInstance().getByProvincialcode(pro_code).getId(); List<City> citys = CityService.getInstance().getCitysByProvincialId(pro_id); List<Option> coptions = new ArrayList<Option>(citys.size()); for (City city : citys) { Option coption = new Option(); coption.setId(city.getId()); coption.setName(city.getCname()); coption.setValue(city.getCode()); // 市級菜單被選中 if (city_code != null && !city_code.equals("")) { if (city.getCode().equals(city_code)) { coption.setSelected("selected"); } } coptions.add(coption); } renderJson(response, coptions); } else { List<Provincial> provincials = ProvincialService.getInstance().getProvincials(); // 轉換成標准的option屬性(name,value,selected) List<Option> options = new ArrayList<Option>(provincials.size()); // 被選中的省市 // 則說明是展示頁面,此時需要為省級菜單和市級菜單設置選擇項 if (city_code != null && !city_code.equals("")) { Provincial selected_provincial = ProvincialService.getInstance().getProvincialByCitycode(city_code); pro_code = selected_provincial.getProcode(); } else { pro_code = provincials.get(0) == null ? "" : provincials.get(0).getProcode(); } for (Provincial provincial : provincials) { Option option = new Option(); option.setId(provincial.getId()); option.setName(provincial.getProname()); option.setValue(provincial.getProcode()); if (!pro_code.equals("") && provincial.getProcode().equals(pro_code)) { option.setSelected("selected"); } options.add(option); } renderJson(response, JsonUtil.toJson(options)); } } catch (Exception e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); renderJson(response, null); } } }
@RequestParam(value = "city_code", required = false) String city_code,對於RequestParam注解,其實非常好用,這裡就不多做解釋,只是推廣一下,固定個數的參數,用該注解更易於代碼的維護。
ProvincialService類、CityService類就是兩個單例,盡量把數據放置在內存當中,減少查詢數據庫的次數,稍候貼出來一個例子。
Option類就是單純的封裝前端option組件的關鍵屬性,便於組件的通用化。
renderJson(response, JsonUtil.toJson(options));將數據json化後返回,稍候貼上詳細代碼。
④、ProvincialService.java
只貼出來代碼例子,不做詳細解釋,畢竟不是本章重點。
package com.honzh.spring.service; import java.util.ArrayList; import java.util.List; import com.honzh.biz.database.entity.City; import com.honzh.biz.database.entity.Provincial; import com.honzh.biz.database.mapper.ProvincialMapper; import com.honzh.common.spring.SpringContextHolder; public class ProvincialService { private static Object lock = new Object(); private static ProvincialService config = null; private ProvincialService() { provincials = new ArrayList<Provincial>(); ProvincialMapper mapper = SpringContextHolder.getBean(ProvincialMapper.class); provincials.addAll(mapper.getProvincials()); } public static ProvincialService getInstance() { synchronized (lock) { if (null == config) { config = new ProvincialService(); } } return (config); } public Provincial getByProvincialcode(String provincial_code) { for (Provincial provincial : provincials) { if (provincial.getProcode().equals(provincial_code)) { return provincial; } } return null; } private List<Provincial> provincials = null; public List<Provincial> getProvincials() { return provincials; } public Provincial getProvincialByCitycode(String city_code) { City city = CityService.getInstance().getCityByCode(city_code); for (Provincial provincial : provincials) { if (provincial.getId().intValue() == city.getProid().intValue()) { return provincial; } } return null; } public Provincial getProvincialByCode(String province_code) { for (Provincial provincial : provincials) { if (provincial.getProcode().equals(province_code)) { return provincial; } } return null; } }
⑤、renderJson方法
/** * 如果出錯的話,response直接返回404 */ protected void renderJson(HttpServletResponse response, Object responseObject) { PrintWriter out = null; try { if (responseObject == null) { response.sendError(404); return; } // 將實體對象轉換為JSON Object轉換 String responseStr = JsonUtil.toJson(responseObject); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); out = response.getWriter(); out.append(responseStr); logger.debug("返回是:" + responseStr); } catch (IOException e) { logger.error(e.getMessage()); logger.error(e.getMessage(), e); } finally { if (out != null) { out.close(); } } }
如果大家還想深入學習,可以點擊jQuery級聯菜單特效匯總、Javascript級聯菜單特效匯總進行學習。
如果大家還想深入學習Bootstrap,可以點擊這裡進行學習,再為大家附兩個精彩的專題:Bootstrap學習教程 Bootstrap實戰教程
本文系列教程整理到:Bootstrap基礎教程 專題中,歡迎點擊學習。
以上就是本文的全部內容,希望對大家的學習有所幫助。