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

本文涉及的产品
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: 二、导入css和js到网站上1.使用CDN,节省自己网站的流量?122.下载文件到本地,可以做一些个性的定制(比如说修改提示语)git下载地址?12345三、真刀真枪的干起来第一步、定制页面个性化元素?123 沉默王二Java端通过name属性可获得select的value值。

本地实战结果

二、导入css和js到网站上

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

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

git下载地址

?
1
2
3
4
5
<!-- 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>

三、真刀真枪的干起来

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

?
1
2
3
<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组件化,注释写得很详细了哦

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<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端接收参数并返回结果集,不用我强调,这步很重要

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@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);
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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端分页参数匹配

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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端的数据封装

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@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进行转换匹配

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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就会自动为你分页,这个就厉害了。

?
1
List getPromoterList(BaseConditionVO vo, RowBounds createRowBounds);

sql语句,这里的关键点是必须要回传id(m.uid as id)到select2.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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,嗯,这里无须关注,这就是框架要为我们做的事情。

总数

?
1
int searchPromoterTotalCount(BaseConditionVO vo);

count(0)就好

?
1
2
3
4
5
6
7
<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中

?
1
2
3
4
5
6
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的源码可以知道。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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中找到以下代码,注意注释部分

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

?
1
2
3
4
5
6
7
this .defaults = {
...
  minimumInputLength: 0,
  inputMessage: '' ,
  maximumInputLength: 0,
  ...
};

然后在zh-CN.js文件中修改inputTooShort方法

?
1
2
3
4
5
6
7
8
inputTooShort : function (e) {
  if (e.inputMessage) {
   return e.inputMessage; // 增加inputMessage
  } else {
   var t = e.minimum - e.input.length, n = "请再输入至少" + t + "个字符" ;
   return n
  }
},

 

 

原文链接:http://blog.csdn.net/qing_gee/article/details/72519313

相关实践学习
基于MaxCompute的热门话题分析
本实验围绕社交用户发布的文章做了详尽的分析,通过分析能得到用户群体年龄分布,性别分布,地理位置分布,以及热门话题的热度。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
目录
相关文章
|
7月前
|
前端开发 JavaScript
js + ajax实现商品列表页到详情页的跳转
js + ajax实现商品列表页到详情页的跳转
|
前端开发
JavaWeb15(AJAX+JSON实现无刷新分页)
JavaWeb15(AJAX+JSON实现无刷新分页)
|
3月前
|
前端开发
React技术栈-react使用的Ajax请求库用户搜索案例
这篇文章展示了一个React技术栈中使用Ajax请求库(如axios)进行用户搜索的实战案例,包括React组件的结构、状态管理以及如何通过Ajax请求获取并展示GitHub用户数据。
36 7
React技术栈-react使用的Ajax请求库用户搜索案例
|
2月前
|
JSON JavaScript 前端开发
《进阶篇第7章》学习vue中的ajax之后,练习vue案例-github用户搜索案例
《进阶篇第7章》学习vue中的ajax之后,练习vue案例-github用户搜索案例
17 0
|
前端开发
Echarts实战案例代码(21):front-endPage的CJJTable前端分页插件ajax分页异步加载数据的解决方案
Echarts实战案例代码(21):front-endPage的CJJTable前端分页插件ajax分页异步加载数据的解决方案
93 0
|
前端开发 JavaScript Java
Jquery+Ajax+Bootstrap Paginator实现分页的拼接
Jquery+Ajax+Bootstrap Paginator实现分页的拼接
58 0
|
开发框架 前端开发 .NET
用ajax和asp.net实现智能搜索功能
用ajax和asp.net实现智能搜索功能
79 0
|
前端开发 Java
教你实现SSM和Ajax后端分页
教你实现SSM和Ajax后端分页
|
前端开发
【(不用Ajax)解决 Layui 插件分页点下一页后又自动跳回前一页的问题】
【(不用Ajax)解决 Layui 插件分页点下一页后又自动跳回前一页的问题】
178 0
|
23天前
|
存储 分布式计算 数据挖掘
数据架构 ODPS 是什么?
数据架构 ODPS 是什么?
181 7