jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)


Posted in jQuery onMay 19, 2017

select2是一款jQuery插件,是普通form表单select组件的升级版。

可以定制搜索、远程数据集(Remote data,本篇主要介绍点)、无限滚动(数据分页功能,这一点很妙)、还有很多高端的参数设置(有需要的下次介绍)。

内置了40种国际化语言,不过这里我们只需要用到中文。

同时支持现代和传统浏览器内置,甚至包括惹人不高兴的IE8。

那么,现在让我们开始一段select2的奇幻之旅吧!

一、惊艳的效果,来一睹为快吧

jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)
jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)
jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)

本地实战结果

jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)

二、导入css和js到网站上

1.使用CDN,节省自己网站的流量

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="external nofollow" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>

2.下载文件到本地,可以做一些个性的定制(比如说修改提示语)

git下载地址

<!-- 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>
<!-- 中文国际化还需要进行参数设置 -->
<script type="text/javascript" src="${ctx}/common/select2/js/i18n/zh-CN.js"></script>

三、真刀真枪的干起来

第一步、定制页面个性化元素

<select name="parentid" class="js-data-example-ajax" href="${ctx}/member/loadMembersInfo.do?uid=${mem.uid}" rel="external nofollow" style="width:400px" inputMessage="请输入会员编号(可部分匹配)">
 <option selected="selected" value="666">沉默王二</option>
</select>

Java端通过name属性可获得select的value值。

设置class为js-data-example-ajax,页面加载时对该组件进行select2的初始化。

href属性为ajax提供后台检索的URL。

style设置组件的宽度。

inputMessage属性定制个性化的提示语,默认的英文版为Please enter 1 or more characters,中文国际化为“请再输入至少1个字符”,都不太能满足个性化需求,所以需要改,后面介绍。
提供一个默认的option,页面没检索之前显示。

第二步、select2组件化,注释写得很详细了哦

<script type="text/javascript">
 $(function() {
  $("select.js-data-example-ajax").each(
  function() {
   var $this = $(this);
   $this.select2({
    language : "zh-CN",// 指定语言为中文,国际化才起效
    inputMessage : $this.attr("inputMessage"),// 添加默认参数
    ajax : {
     url : $this.attr("href"),
     dataType : 'json',
     delay : 250,// 延迟显示
     data : function(params) {
      return {
       username : params.term, // 搜索框内输入的内容,传递到Java后端的parameter为username
       page : params.page,// 第几页,分页哦
       rows : 10// 每页显示多少行
      };
     },
     // 分页
     processResults : function(data, params) {
      params.page = params.page || 1;
      return {
       results : data.data,// 后台返回的数据集
       pagination : {
        more : params.page < data.total// 总页数为10,那么1-9页的时候都可以下拉刷新
       }
      };
     },
     cache : false
    },
    escapeMarkup : function(markup) {
     return markup;
    }, // let our custom formatter work
    minimumInputLength : 1,// 最少输入一个字符才开始检索
    templateResult : function(repo) {// 显示的结果集格式,这里需要自己写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> 下级会员数" + repo.children_count + " </div>"
       + "</div>" + "</div></div>";
     return markup;
    }, 
    templateSelection : function(repo) {
     return repo.realname || repo.text;
    }// 列表中选择某一项后显示到文本框的内容
   });
  });
 });
</script>

第三步、Java端接收参数并返回结果集,不用我强调,这步很重要

@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);
 // 分页参数的转换,需要和前台select2进行匹配,下文放代码
 BaseConditionVO vo = getBaseConditionVOForTable(request);
 vo.addParams("username", StrUtil.getUTF8String(request.getParameter("username")));
 vo.addParams("uid", uid);
 // 封装结果集,和前台select2也是匹配的。
 PageGrid page = createPageGrid(this.membersMapper.getPromoterList(vo, vo.createRowBounds()), vo,
   this.membersMapper.searchPromoterTotalCount(vo));
 // 以json格式写入到response
 out(page, response);
}

接下来,把关键的源码贴出来,可能和你的项目不吻合,但可以参考。

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 : 对参数类型进行封装.
  */
 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的分页和Java端分页参数匹配

protected BaseConditionVO getBaseConditionVOForTable(HttpServletRequest req) {
 BaseConditionVO vo = new BaseConditionVO();
 // 当前页
 int currentPage = StrUtil.parseStringToInt(req.getParameter("page"));
 // 一页显示多少行
 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端的数据封装

@XStreamAlias("pageGrid")
@SuppressWarnings("rawtypes")
public class PageGrid {
 private int page;
 // 总页数,和select2的processResults.pagination匹配
 private int total;
 private int records;
 // 数据结果集,和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获取的数据源和PageGrid进行转换匹配

protected PageGrid createPageGrid(List list, BaseConditionVO vo, int searchTotalCount) {
 PageGrid pageGrid = new PageGrid();
 // 数据
 pageGrid.setData(list);
 // 当前页
 pageGrid.setPage(vo.getPageNum());
 // 总数目
 pageGrid.setRecords(list.size());
 // 总页数
 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的分页,超简单,只要设置了createRowBounds,mybatis就会自动为你分页,这个就厉害了。

List getPromoterList(BaseConditionVO vo, RowBounds createRowBounds);

sql语句,这里的关键点是必须要回传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>

你是不是没看见mysql的分页limit,嗯,这里无须关注,这就是框架要为我们做的事情。

总数

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功能在代码部分就完全贴出来完了。

不过,我最后还是要强调几个点:

1.分页的参数Java端和select2一定要对照起来。

2.回传的数据一定要传递一个id回来,否则回来的列表不能选中,为什么呢?调查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恰好又是列表选中的关键属性。
// 这个就是个坑,只能这么说,select2给出的api上完全不讲这点,我去!!!!!!!
 if (data.id == null) {
  delete attrs['aria-selected'];
 }
 ......
}

3.form表单如何获取select2的值?答案是,1.返回结果集必须有id,2.input标签上必须要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 = "请再输入至少" + t + "个字符";
  return n
 }
},

以上所述是小编给大家介绍的jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

jQuery 相关文章推荐
jquery submit()不能提交表单的解决方法
Apr 24 jQuery
jQuery实现可兼容IE6的淡入淡出效果告警提示功能示例
Sep 20 jQuery
jQuery中 DOM节点操作方法大全
Oct 12 jQuery
利用jQuery实现简单的拖曳效果实例代码
Oct 20 jQuery
jQuery实现右侧抽屉式在线客服功能
Dec 25 jQuery
[原创]jQuery实现合并/追加数组并去除重复项的方法
Apr 11 jQuery
详解使用jQuery.i18n.properties实现js国际化
May 04 jQuery
jQuery简单实现根据日期计算星期几的方法
Jan 09 jQuery
JQueryDOM之样式操作
Mar 27 jQuery
jQuery实现高级检索功能
May 28 jQuery
jQuery实现简易聊天框
Feb 08 jQuery
JavaScript或jQuery 获取option value值方法解析
May 12 jQuery
jQuery操作之效果详解
May 19 #jQuery
jQuery Validate 校验多个相同name的方法
May 18 #jQuery
jQuery Validate 无法验证 chosen-select元素的解决方法
May 17 #jQuery
jQuery查找dom的几种方法效率详解
May 17 #jQuery
jQuery实现div跟随鼠标移动
Aug 20 #jQuery
jquery+ajax实现省市区三级联动 (封装和不封装两种方式)
May 15 #jQuery
Jquery把获取到的input值转换成json
May 15 #jQuery
You might like
DC这些乐高系列动画电影你看过几部?
2020/04/09 欧美动漫
MySQL相关说明
2007/01/15 PHP
centos7上编译安装php7以php-fpm方式连接apache
2018/11/08 PHP
Laravel5.5 数据库迁移:创建表与修改表示例
2019/10/23 PHP
JavaScript实现拼音排序的方法
2012/11/20 Javascript
javaScript中的this示例学习详解及工作原理
2014/01/13 Javascript
js 赋值包含单引号双引号问题的解决方法
2014/02/26 Javascript
Javascript中使用parseInt函数需要注意的问题
2015/04/02 Javascript
jQuery实现仿美橙互联两级导航菜单效果完整实例
2015/09/17 Javascript
CSS中position属性之fixed实现div居中
2015/12/14 Javascript
Javascript将双字节字符转换成单字节字符并计算长度
2016/06/22 Javascript
vue插件tab选项卡使用小结
2016/10/27 Javascript
jquery事件与绑定事件
2017/03/16 Javascript
Javarscript中模块(module)、加载(load)与捆绑(bundle)详解
2017/05/28 Javascript
node实现定时发送邮件的示例代码
2017/08/26 Javascript
js排序与重组的实例讲解
2017/08/28 Javascript
Node.JS使用Sequelize操作MySQL的示例代码
2017/10/09 Javascript
解决layer弹出层中表单不起作用的问题
2019/09/09 Javascript
javascript实现商品图片放大镜
2019/11/28 Javascript
微信小程序返回上一级页面的实现代码
2020/06/19 Javascript
Vue如何将页面导出成PDF文件
2020/08/17 Javascript
基于JavaScript实现简单的轮播图
2021/03/03 Javascript
Python Tkinter简单布局实例教程
2014/09/03 Python
Python 实现选择排序的算法步骤
2018/04/22 Python
如何理解python对象
2020/06/21 Python
解决tensorflow/keras时出现数组维度不匹配问题
2020/06/29 Python
如何以Winsows Service方式运行JupyterLab
2020/08/30 Python
selenium设置浏览器为headless无头模式(Chrome和Firefox)
2021/01/08 Python
纯CSS3实现Material Design效果
2017/03/09 HTML / CSS
HTML5 video标签(播放器)学习笔记(一):使用入门
2015/04/24 HTML / CSS
贝玲妃英国官网:Benefit英国
2018/02/03 全球购物
马来西亚在线健康商店:Medipal Malaysia
2020/04/13 全球购物
政风行风建设整改方案
2014/10/27 职场文书
三下乡个人总结
2015/03/04 职场文书
我的长征观后感
2015/06/09 职场文书
小学运动会通讯稿
2015/07/18 职场文书