jQuery插件select2利用ajax高效查詢大數(shù)據(jù)列表(可搜索、可分頁(yè))
select2是一款jQuery插件,是普通form表單select組件的升級(jí)版。
可以定制搜索、遠(yuǎn)程數(shù)據(jù)集(Remote data,本篇主要介紹點(diǎn))、無(wú)限滾動(dòng)(數(shù)據(jù)分頁(yè)功能,這一點(diǎn)很妙)、還有很多高端的參數(shù)設(shè)置(有需要的下次介紹)。
內(nèi)置了40種國(guó)際化語(yǔ)言,不過(guò)這里我們只需要用到中文。
同時(shí)支持現(xiàn)代和傳統(tǒng)瀏覽器內(nèi)置,甚至包括惹人不高興的IE8。
那么,現(xiàn)在讓我們開(kāi)始一段select2的奇幻之旅吧!
一、驚艷的效果,來(lái)一睹為快吧
本地實(shí)戰(zhàn)結(jié)果
二、導(dǎo)入css和js到網(wǎng)站上
1.使用CDN,節(jié)省自己網(wǎng)站的流量
<link rel="external nofollow" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
2.下載文件到本地,可以做一些個(gè)性的定制(比如說(shuō)修改提示語(yǔ))
<!-- select2 --> <link rel="stylesheet" type="text/css" href="${ctx}/common/select2/css/select2.css" rel="external nofollow" /> <script type="text/javascript" src="${ctx}/common/select2/js/select2.full.js"></script> <!-- 中文國(guó)際化還需要進(jìn)行參數(shù)設(shè)置 --> <script type="text/javascript" src="${ctx}/common/select2/js/i18n/zh-CN.js"></script>
三、操作起來(lái)
第一步、定制頁(yè)面?zhèn)€性化元素
<select name="parentid" class="js-data-example-ajax" href="${ctx}/member/loadMembersInfo.do?uid=${mem.uid}" rel="external nofollow" style="width:400px" inputMessage="請(qǐng)輸入會(huì)員編號(hào)(可部分匹配)"> <option selected="selected" value="666">沉默王二</option> </select>
Java端通過(guò)name屬性可獲得select的value值。
設(shè)置class為js-data-example-ajax,頁(yè)面加載時(shí)對(duì)該組件進(jìn)行select2的初始化。
href屬性為ajax提供后臺(tái)檢索的URL。
style設(shè)置組件的寬度。
inputMessage屬性定制個(gè)性化的提示語(yǔ),默認(rèn)的英文版為Please enter 1 or more characters,中文國(guó)際化為“請(qǐng)?jiān)佥斎胫辽?個(gè)字符”,都不太能滿足個(gè)性化需求,所以需要改,后面介紹。
提供一個(gè)默認(rèn)的option,頁(yè)面沒(méi)檢索之前顯示。
第二步、select2組件化,注釋寫(xiě)得很詳細(xì)了哦
<script type="text/javascript"> $(function() { $("select.js-data-example-ajax").each( function() { var $this = $(this); $this.select2({ language : "zh-CN",// 指定語(yǔ)言為中文,國(guó)際化才起效 inputMessage : $this.attr("inputMessage"),// 添加默認(rèn)參數(shù) ajax : { url : $this.attr("href"), dataType : 'json', delay : 250,// 延遲顯示 data : function(params) { return { username : params.term, // 搜索框內(nèi)輸入的內(nèi)容,傳遞到Java后端的parameter為username page : params.page,// 第幾頁(yè),分頁(yè)哦 rows : 10// 每頁(yè)顯示多少行 }; }, // 分頁(yè) processResults : function(data, params) { params.page = params.page || 1; return { results : data.data,// 后臺(tái)返回的數(shù)據(jù)集 pagination : { more : params.page < data.total// 總頁(yè)數(shù)為10,那么1-9頁(yè)的時(shí)候都可以下拉刷新 } }; }, cache : false }, escapeMarkup : function(markup) { return markup; }, // let our custom formatter work minimumInputLength : 1,// 最少輸入一個(gè)字符才開(kāi)始檢索 templateResult : function(repo) {// 顯示的結(jié)果集格式,這里需要自己寫(xiě)css樣式,可參照demo // 正在檢索 if (repo.loading) return repo.text; var markup = repo.username; markup += repo.realname; var markup = "<div class='select2-result-repository clearfix'>" + "<div class='select2-result-repository__avatar'><img src='" + repo.headimgUrl + "' /></div>" + "<div class='select2-result-repository__meta'>" + "<div class='select2-result-repository__title'>" + repo.username + "</div>"; if (repo.realname) { markup += "<div class='select2-result-repository__description'>" + repo.realname + "</div>"; } markup += "<div class='select2-result-repository__statistics'>" + "<div class='select2-result-repository__forks'><i class='fa fa-user'></i> 下級(jí)會(huì)員數(shù)" + repo.children_count + " </div>" + "</div>" + "</div></div>"; return markup; }, templateSelection : function(repo) { return repo.realname || repo.text; }// 列表中選擇某一項(xiàng)后顯示到文本框的內(nèi)容 }); }); }); </script>
第三步、Java端接收參數(shù)并返回結(jié)果集,不用我強(qiáng)調(diào),這步很重要
@RequestMapping(value = "loadMembersInfo") public void loadMembersInfo(HttpServletRequest request, HttpServletResponse response) throws IOException { Integer uid = StrUtil.parseStringToInt(request.getParameter("uid")); Members mem = this.memberService.selectByPrimaryKey(uid); // 分頁(yè)參數(shù)的轉(zhuǎn)換,需要和前臺(tái)select2進(jìn)行匹配,下文放代碼 BaseConditionVO vo = getBaseConditionVOForTable(request); vo.addParams("username", StrUtil.getUTF8String(request.getParameter("username"))); vo.addParams("uid", uid); // 封裝結(jié)果集,和前臺(tái)select2也是匹配的。 PageGrid page = createPageGrid(this.membersMapper.getPromoterList(vo, vo.createRowBounds()), vo, this.membersMapper.searchPromoterTotalCount(vo)); // 以json格式寫(xiě)入到response out(page, response); }
接下來(lái),把關(guān)鍵的源碼貼出來(lái),可能和你的項(xiàng)目不吻合,但可以參考。
BaseConditionVO.Java public class BaseConditionVO { public final static int PAGE_SHOW_COUNT = 50; private int pageNum = 1; private int numPerPage = 0; private int totalCount = 0; private String orderField; private String orderDirection; /** * @Fields ps : 對(duì)參數(shù)類型進(jìn)行封裝. */ private Map<String, Object> mo = new HashMap<String, Object>(); public int getPageNum() { return pageNum; } public void setPageNum(int pageNum) { this.pageNum = pageNum; } public int getNumPerPage() { return numPerPage > 0 ? numPerPage : PAGE_SHOW_COUNT; } public void setNumPerPage(int numPerPage) { this.numPerPage = numPerPage; } public String getOrderField() { return orderField; } public void setOrderField(String orderField) { this.orderField = orderField; } public String getOrderDirection() { return "desc".equals(orderDirection) ? "desc" : "asc"; } public void setOrderDirection(String orderDirection) { this.orderDirection = orderDirection; } public int getTotalCount() { return totalCount; } public void setTotalCount(int totalCount) { this.totalCount = totalCount; } public int getStartIndex() { int pageNum = this.getPageNum() > 0 ? this.getPageNum() - 1 : 0; return pageNum * this.getNumPerPage(); } public RowBounds createRowBounds() { RowBounds ro = new RowBounds(this.getStartIndex(), this.getNumPerPage()); return ro; } /** * @Title: addParams * @Description: 添加查詢條件 * @param key * @param value */ public void addParams(String key, Object value) { this.getMo().put(key, value); } /** * @Title: getParams * @Description: 獲取查詢條件 * @param key * @return */ public Object getParams(String key) { return this.getMo().get(key); } /** * @return the mo */ public Map<String, Object> getMo() { return mo; } /** * @param mo * the mo to set */ public void setMo(Map<String, Object> mo) { this.mo = mo; } }
selec2的分頁(yè)和Java端分頁(yè)參數(shù)匹配
protected BaseConditionVO getBaseConditionVOForTable(HttpServletRequest req) { BaseConditionVO vo = new BaseConditionVO(); // 當(dāng)前頁(yè) int currentPage = StrUtil.parseStringToInt(req.getParameter("page")); // 一頁(yè)顯示多少行 int sizes = StrUtil.parseStringToInt(req.getParameter("rows")); // 排序 String sortOrder = StrUtil.getString(req.getParameter("sord")); String sortCol = StrUtil.getString(req.getParameter("sidx")); vo.setNumPerPage(sizes); vo.setPageNum(currentPage); vo.setOrderField(sortCol); vo.setOrderDirection(sortOrder); return vo; }
Java端到select2端的數(shù)據(jù)封裝
@XStreamAlias("pageGrid") @SuppressWarnings("rawtypes") public class PageGrid { private int page; // 總頁(yè)數(shù),和select2的processResults.pagination匹配 private int total; private int records; // 數(shù)據(jù)結(jié)果集,和select2的processResults.results匹配 private List data; public int getPage() { return this.page; } public void setPage(int page) { this.page = page; } public int getTotal() { return this.total; } public void setTotal(int total) { this.total = total; } public int getRecords() { return this.records; } public void setRecords(int records) { this.records = records; } public List getData() { return this.data; } public void setData(List data) { this.data = data; } }
MySQL獲取的數(shù)據(jù)源和PageGrid進(jìn)行轉(zhuǎn)換匹配
protected PageGrid createPageGrid(List list, BaseConditionVO vo, int searchTotalCount) { PageGrid pageGrid = new PageGrid(); // 數(shù)據(jù) pageGrid.setData(list); // 當(dāng)前頁(yè) pageGrid.setPage(vo.getPageNum()); // 總數(shù)目 pageGrid.setRecords(list.size()); // 總頁(yè)數(shù) int total = 0; if (pageGrid.getRecords() != 0) { total = searchTotalCount % vo.getNumPerPage() == 0 ? searchTotalCount / vo.getNumPerPage() : searchTotalCount / vo.getNumPerPage() + 1; } pageGrid.setTotal(total); return pageGrid; }
mybatis的分頁(yè),超簡(jiǎn)單,只要設(shè)置了createRowBounds,mybatis就會(huì)自動(dòng)為你分頁(yè),這個(gè)就厲害了。
List getPromoterList(BaseConditionVO vo, RowBounds createRowBounds);
sql語(yǔ)句,這里的關(guān)鍵點(diǎn)是必須要回傳id(m.uid as id)到select2.
<select id="getPromoterList" resultType="hashmap" parameterType="map"> select m.uid as id, convert(m.username,char) username, m.realname, m.children_count, m.headimgUrl from members m where m.deleteflag=0 <if test="mo.username != ''">and m.username like CONCAT('%', '${mo.username}', '%')</if> <choose> <when test="orderField !=null and orderField !=''"> ORDER BY ${orderField} <if test="orderDirection != null and orderDirection != ''">${orderDirection}</if> </when> <otherwise> order by m.username DESC </otherwise> </choose> </select>
你是不是沒(méi)看見(jiàn)mysql的分頁(yè)limit,嗯,這里無(wú)須關(guān)注,這就是框架要為我們做的事情。
總數(shù)
int searchPromoterTotalCount(BaseConditionVO vo);
count(0)就好
<select id="searchPromoterTotalCount" resultType="java.lang.Integer" parameterType="map"> select count(0) as a from members m where m.deleteflag=0 <if test="mo.username != ''">and m.username like CONCAT('%', '${mo.username}', '%')</if> </select>
out輸出到response中
protected void out(Object result, HttpServletResponse response) throws IOException { ServletOutputStream out = response.getOutputStream(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.writeValue(out, result); out.flush(); }
到這,select2的remote功能在代碼部分就完全貼出來(lái)完了。
不過(guò),我最后還是要強(qiáng)調(diào)幾個(gè)點(diǎn):
1.分頁(yè)的參數(shù)Java端和select2一定要對(duì)照起來(lái)。
2.回傳的數(shù)據(jù)一定要傳遞一個(gè)id回來(lái),否則回來(lái)的列表不能選中,為什么呢?調(diào)查select2的源碼可以知道。
Results.prototype.option = function (data) { var option = document.createElement('li'); option.className = 'select2-results__option'; var attrs = { 'role': 'treeitem', 'aria-selected': 'false' }; if (data.disabled) { delete attrs['aria-selected']; attrs['aria-disabled'] = 'true'; } // id為空的情況下,刪除的aria-selected,而aria-selected恰好又是列表選中的關(guān)鍵屬性。 // 這個(gè)就是個(gè)坑,只能這么說(shuō),select2給出的api上完全不講這點(diǎn),我去?。。。。。?! if (data.id == null) { delete attrs['aria-selected']; } ...... }
3.form表單如何獲取select2的值?答案是,1.返回結(jié)果集必須有id,2.input標(biāo)簽上必須要name屬性。
4.如何自定義inputMessage呢?
在select2.js中找到以下代碼,注意注釋部分
S2.define('select2/data/minimumInputLength',[ ], function () { function MinimumInputLength (decorated, $e, options) { this.minimumInputLength = options.get('minimumInputLength'); // inputMessage this.inputMessage = options.get('inputMessage'); decorated.call(this, $e, options); } MinimumInputLength.prototype.query = function (decorated, params, callback) { params.term = params.term || ''; if (params.term.length < this.minimumInputLength) { this.trigger('results:message', { message: 'inputTooShort', args: { minimum: this.minimumInputLength, input: params.term, inputMessage : this.inputMessage, // inputMessage,傳遞給i18n params: params } }); return; } decorated.call(this, params, callback); }; return MinimumInputLength; });
select2.js中defaults中增加上inputMessage
this.defaults = { ... minimumInputLength: 0, inputMessage: '', maximumInputLength: 0, ... };
然后在zh-CN.js文件中修改inputTooShort方法
inputTooShort : function(e) { if (e.inputMessage) { return e.inputMessage;// 增加inputMessage } else { var t = e.minimum - e.input.length, n = "請(qǐng)?jiān)佥斎胫辽? + t + "個(gè)字符"; return n } },
以上所述是小編給大家介紹的jQuery插件select2利用ajax高效查詢大數(shù)據(jù)列表(可搜索、可分頁(yè)),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
基于jquery的無(wú)限級(jí)聯(lián)下拉框js插件
首先聲明這2個(gè)無(wú)刷新級(jí)聯(lián)下拉框的jquery插件完全是自己原創(chuàng)的,經(jīng)過(guò)嚴(yán)格的測(cè)試,正確使用不會(huì)出現(xiàn)bug2011-10-10jQuery fadeTo方法調(diào)整圖片的透明度使用介紹
利用jquery的fadeTo方法可以簡(jiǎn)單的制作一些很不錯(cuò)的動(dòng)畫(huà)效果.可以使圖片或者文字或者區(qū)塊以不同的透明度效果出現(xiàn).例如以下練習(xí)實(shí)例,感興趣的朋友可以參考下哈2013-05-05使用JQUERY進(jìn)行后臺(tái)頁(yè)面布局控制DIV實(shí)現(xiàn)左右式
一個(gè)網(wǎng)站的后臺(tái)使用frame框架來(lái)實(shí)現(xiàn)這種形式,這邊作者不是使用的frame而是純div進(jìn)行布局,下面看下具體的實(shí)現(xiàn)代碼2014-01-01Easyui Datagrid自定義按鈕列(最后面的操作列)
做項(xiàng)目的時(shí)候因?yàn)樾枨?要在表格的最后添加一列操作列,easyUI貌似沒(méi)有提供這種功能,下面我們來(lái)自定義按鈕列,具體實(shí)現(xiàn)代碼,大家參考下本文吧2017-07-07jQuery Datatables 動(dòng)態(tài)列+跨列合并實(shí)現(xiàn)代碼
這篇文章主要介紹了jQuery Datatables 動(dòng)態(tài)列+跨列合并實(shí)現(xiàn)代碼,需要的朋友可以參考下2020-01-01Jquery中$.post和$.ajax的用法小結(jié)
本節(jié)重點(diǎn)講的是jquery中調(diào)用ajax的4種方法中最常用的:$.post、和$ajax。如果讀者沒(méi)有javascript和jquery的知識(shí),或者沒(méi)有ajax的概念,那么請(qǐng)先去問(wèn)問(wèn)度娘,再來(lái)讀本文。2015-04-04JQuery的Ajax請(qǐng)求實(shí)現(xiàn)局部刷新的簡(jiǎn)單實(shí)例
本篇文章只要是對(duì)JQuery的Ajax請(qǐng)求實(shí)現(xiàn)局部刷新的簡(jiǎn)單實(shí)例進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-02-02