select2,利用ajax高效查询大数据列表(可搜索、可分页)
二、导入css和js到网站上
1.使用CDN,节省自己网站的流量
1
2
|
<link href= "https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel= "external nofollow" rel= "stylesheet" /> |
2.下载文件到本地,可以做一些个性的定制(比如说修改提示语)
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
select2,利用ajax高效查询大数据列表(可搜索、可分页)的更多相关文章
- 利用Javascript解决HTML大数据列表引起的网页加载慢/卡死问题。
在一些网页应用中,有时会碰到一个超级巨大的列表,成千上万行,这时大部份浏览器解析起来就非常痛苦了(有可能直接卡死). 也许你们会说可以分页或动态加载啊?但是有可能需求不允许分页,动态加载?网络的延迟也 ...
- 关于MySQL中查询大数据量的情况下分页limit的性能优化
https://blog.csdn.net/weixin_37848710/article/details/80772725
- 在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析
在HDInsight中从Hadoop的兼容BLOB存储查询大数据的分析 低成本的Blob存储是一个强大的.通用的Hadoop兼容Azure存储解决方式无缝集成HDInsight.通过Hadoop分布式 ...
- WinForm查询大数据界面假死,使用异步调用解决
用DataGridView无分页绑定一个几千条数据的查询,查询的时候界面直接卡死十几秒,用户体验非常不好,因此用异步操作解决界面卡死的问题原本场景:点击[查询]后,界面直接卡死优化场景:点击[查询]后 ...
- CANN算子:利用迭代器高效实现Tensor数据切割分块处理
摘要:本文以Diagonal算子为例,介绍并详细讲解如何利用迭代器对n维Tensor进行基于位置坐标的大批量数据读取工作. 本文分享自华为云社区<CANN算子:利用迭代器高效实现Tensor数据 ...
- 利用jdbc处理oracle大数据---大文件和二进制文件
一.Oracle中大数据处理 在Oracle中,LOB(Large Object,大型对象)类型的字段现在用得越来越多了.因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种 ...
- mongoTemplate查询大数据过慢
先上两段代码 代码一 Query query = new Query();queryAfter.addCriteria(Criteria.where("id").in(idList ...
- 查询大数据表的效率对比:Linq to SQL、Entity Framework、企业库存储过程、ADO.Net
最近因为要开发大数据量网站,特作比较. Linq to SQL 查询 记录数:399997Linq to SQL 查询 Milliseconds:1910视图查询 记录数:399997视图查询 Mil ...
- MySQL分页查询大数据量优化方法
方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N适应场景: 适用于数据量较少的情况(元组百/千级)原因/缺点: ...
随机推荐
- 计算机网络 --万维网www
万维网是一个分布式的超媒体系统,客户程序向服务器程序发出请求,服务器程序向客户程序送回客户所需要的万维网文档.万维网必须解决的几个问题:1.怎样标志分布在整个因特网上的万维网文档?答:万维网使用统一的 ...
- Hadoop实战-Flume之Source replicating(十四)
a1.sources = r1 a1.sinks = k1 k2 a1.channels = c1 c2 # Describe/configure the source a1.sources.r1.t ...
- nvl()与regexp_replace()
NVL(字段,0):将空值转化为0 regexp_replace(字段, ‘[1-9]‘ ,'') is not null; 将数字转化为0
- <JAVA8新增内容>关于集合的操作(Collection/Iterator/Stream)
因为下文频繁使用lambda表达式,关于Java中的lambda表达式内容请见: http://www.cnblogs.com/guguli/p/4394676.html 一.使用增强的Iterato ...
- visual studio for mac 安装文件
安装步骤参考: http://jingyan.baidu.com/article/00a07f3869b81082d028dca8.html 所需安装文件:[注 我只下载了javajdk, 需要and ...
- CEF与MLS快速交换对比
MLS快速交换 到达某特定目的地址的IP包通常会引起数据包流,即假设交换过到特定目标的包之后,另一个很可能不久也会到达.通过构建最近交换目标的高速缓存,可以减少包在全路由表中查找同一目标的次数,这种“ ...
- openfire build
1. build path: a) source folder:包括openfire和各插件的代码. b) libraries:build/lib下jar包和插件下jar包,jdk/lib/tools ...
- 破解 Navicat Premium 12
一.下载 若文件百度云链接失效,请发邮件给博主:1766211120@qq.com 1.安装文件下载 v12.0.11(x64)版本下载地址如下 链接:https://pan.baidu.com/s/ ...
- 1>/dev/null 2>&1 & 意思解析
原文:https://jingyan.baidu.com/article/6dad5075334e26a123e36e31.html 用 /dev/null 2>&1 这样的写法.这条命 ...
- STL中mem_fun和mem_fun_ref的用法
例如:假设有如下的代码: class Employee { public: int DoSomething(){} } std::vector<Employee> Emps; 假设我们要调 ...