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 相关文章推荐
JS/jquery实现一个网页内同时调用多个倒计时的方法
Apr 27 jQuery
jQuery实现 RadioButton做必选校验功能
Jun 15 jQuery
利用jQuery+localStorage实现一个简易的计时器示例代码
Dec 25 jQuery
JQuery选中select组件被选中的值方法
Mar 08 jQuery
基于jQuery实现Ajax验证用户名是否可用实例
Mar 25 jQuery
jQuery实现的淡入淡出与滑入滑出效果示例
Apr 18 jQuery
jQuery实现鼠标滑过商品小图片上显示对应大图片功能【测试可用】
Apr 27 jQuery
jQuery实现的点击按钮改变样式功能示例
Jul 21 jQuery
jQuery实现参数自定义的文字跑马灯效果
Aug 15 jQuery
jquery获取input输入框中的值
Nov 13 jQuery
jQuery实现数字华容道小游戏(实例代码)
Jan 16 jQuery
js、jquery实现列表模糊搜索功能过程解析
Mar 27 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
全国FM电台频率大全 - 26 西藏自治区
2020/03/11 无线电
PHP session_start()问题解疑(详细介绍)
2013/07/05 PHP
WordPress开发中短代码的实现及相关函数使用技巧
2016/01/05 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
javascript RadioButtonList获取选中值
2009/04/09 Javascript
JavaScript toFixed() 方法
2010/04/15 Javascript
由Javascript实现的页面日历
2011/11/04 Javascript
jquery获取radio值实例
2014/10/16 Javascript
js去字符串前后空格的实现方法
2016/02/26 Javascript
Javascript随机标签云代码实例
2016/06/21 Javascript
JavaScript编程中实现对象封装特性的实例讲解
2016/06/24 Javascript
jQuery选择器总结之常用元素查找方法
2016/08/04 Javascript
用js实现博客打赏功能
2016/10/24 Javascript
用director.js实现前端路由使用实例
2017/01/27 Javascript
深入理解JavaScript中的for循环
2017/02/07 Javascript
JS排序之快速排序详解
2017/04/08 Javascript
jquery中封装函数传递当前元素的方法示例
2017/05/05 jQuery
浅谈Node模块系统及其模式
2017/11/17 Javascript
详解如何用webpack4从零开始构建react开发环境
2019/01/27 Javascript
[01:17:12]职来职往完美电竞专场
2014/09/18 DOTA
python实现的udp协议Server和Client代码实例
2014/06/04 Python
将Django使用的数据库从MySQL迁移到PostgreSQL的教程
2015/04/11 Python
在Python中处理日期和时间的基本知识点整理汇总
2015/05/22 Python
python交互式图形编程实例(二)
2017/11/17 Python
pyqt 实现QlineEdit 输入密码显示成圆点的方法
2019/06/24 Python
Django 导出项目依赖库到 requirements.txt过程解析
2019/08/23 Python
Python数据可视化:幂律分布实例详解
2019/12/07 Python
python argparse传入布尔参数false不生效的解决
2020/04/20 Python
详解Python中openpyxl模块基本用法
2021/02/23 Python
HTML5新特性之用SVG绘制微信logo
2016/02/03 HTML / CSS
Jogun Shop中文官网:韩国知名时尚男装网站
2016/10/12 全球购物
什么是Oracle的后台进程background processes?都有哪些后台进程?
2012/04/26 面试题
工厂保洁员岗位职责
2013/12/04 职场文书
公司门卫工作职责
2014/06/28 职场文书
初中军训感想
2015/08/07 职场文书
MySQL 服务和数据库管理
2021/11/11 MySQL