Bootstrap table是基于 Bootstrap 的 jQuery 表格插件,可以实现单选、多选、排序、分页,以及编辑、导出、过滤(扩展)等等的功能,只需要简单的配置就可以实现上述的功能。
一、Bootstrap table使用
1.链接
GitHub: http://bootstrap-table.wenzhixin.net.cn/zh-cn/
中文文档:http://bootstrap-table.wenzhixin.net.cn/zh-cn/
2.引入
CDN引入:
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.min.css">
<!-- Latest compiled and minified JavaScript -->
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/bootstrap-table.min.js"></script>
<!-- Latest compiled and minified Locales -->
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.11.1/locale/bootstrap-table-zh-CN.min.js"></script>
本地引入:
a.引入 Bootstrap 库(假如你的项目还没有使用)和 bootstrap-table.css 到 head 标签下:
<link rel="stylesheet" href="bootstrap.min.css">
<link rel="stylesheet" href="bootstrap-table.css">
b.引入 jQuery 库,bootstrap 库(假如你的项目还没有使用)和 bootstrap-table.js 到 head 标签下或者在 body 标签关闭之前(一般建议这么做)。
<script src="jquery.min.js"></script>
<script src="bootstrap.min.js"></script>
<script src="bootstrap-table.js"></script>
<-- put your locale files after bootstrap-table.js -->
<script src="bootstrap-table-zh-CN.js"></script>
requireJS引入(此处引入的只是当前js应用到的,公共的都放在了require.config.js文件里):
require(
[ "js/common/require.config.js" ],
function(config) {
var init = function() {
require(
["bootstrap-res/js/plugins/bootstrap-table/bootstrap-table.min.js",
"bootstrap-res/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.js" ],
function(table, zh) {
//编写你自己的代码
}
});
};
config.init(init);
});
3.JavaScript代码
a.基本配置
$('#demo-table').bootstrapTable(
{
method : 'POST',
dataType : 'json',
cache : false,
striped : true, // 是否显示行间隔色
sidePagination : "server", // 分页方式:client客户端分页,server服务端分页(*)
url : url,
contentType : "application/x-www-form-urlencoded",
height : $(window).height() - 80,
width : $(window).width(),
queryParams : queryParams,
minimumCountColumns : 2,
pageNumber : 1, // 初始化加载第一页,默认第一页
clickToSelect : true,
pageSize : 10, // 每页的记录行数(*)
pageList : [ 10, 25, 50, 100 ], // 可供选择的每页的行数(*)
uniqueId : "id", // 每一行的唯一标识,一般为主键列
pagination : true,
toolbar : '#toolbar',
// showRefresh : true,
// showColumns : true,
showToggle : false,
showExport : true,
exportDataType : 'all',
responseHandler : responseHandler,
columns : [
{
title : 'ID',
field : 'id',
halign : 'center',
align : 'left',
valign : 'middle'
},
{
title : '文件名',
field : 'real_name',
halign : 'center',
align : 'left',
valign : 'middle'
},
{
title : '路径',
field : 'file_path',
halign : 'center',
align : 'left',
valign : 'middle'
},
{
title : '操作',
align : 'center',
formatter : function(value, row,index) {
var d = '<a id="preview" class="btn btn-primary" style="height:26px;font-size:10px;" onclick="preview(\''
+ row.id
+ '\')"><i class=" fa fa-search"></i>预览</a> ';
return d;
},
events : {
'click #preview': function(e, value ,row ,index){
//打开文件的方法,在此处调用
alert(row.id);
}
}
} ]
});
b.参数配置和返回值获取方法
//参数配值方法
function queryParams(params) {
var param = {
keyValue : $("#inputContent").val(),
limit : params.limit, // 页面大小
offset : params.offset, // 页码
pageindex : this.pageNumber,
pageSize : this.pageSize,
}
return param;
}
//获取后台返回参数
function responseHandler(res) {
if (res) {
return {
"rows" : res.rows[0].rows,
"total" : res.rows[0].total
};
} else {
return {
"rows" : [],
"total" : 0
};
}
}
c.后台返回参数形式(封装格式有点乱)
"rows": [{
"limit": 10,
"total": 104503,
"offset": 10,
"rows": [
{
"id": "972",
"catalog_id": null,
"file_path": "www.phhnzftav.com",
"file_name": "“这么厉害,这么嚣张,再根据声",
"real_name": "根据声音,如果我猜测的不错……应该就是飞禽怪兽中,极为可怕的‘黑冠",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
},
{
"id": "973",
"catalog_id": null,
"file_path": "www.dqjc.com",
"file_name": "“黑冠金雕,在雕类怪兽中排第三",
"real_name": "排第三。”魏文双眸放光,低沉道,“成年体的黑冠金雕,体长一般达到2",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
},
{
"id": "974",
"catalog_id": null,
"file_path": "www.yzpco.com",
"file_name": "罗峰知道黑冠金雕厉害,可是听到",
"real_name": "是听到一秒1326米的极限速度,依旧感到心中屏息",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
},
{
"id": "975",
"catalog_id": null,
"file_path": "www.qubirbieabo.com",
"file_name": "一秒钟,也就是眼睛一眨啊。就一",
"real_name": "。就一千米开外了",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
},
{
"id": "976",
"catalog_id": null,
"file_path": "www.qxhfgumjcxz.com",
"file_name": "“这黑冠金雕,羽毛比金刚石还要",
"real_name": "石还要坚硬,应该达到三级克罗合金的硬度。”魏文兴奋连道,“网上可是",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
},
{
"id": "977",
"catalog_id": null,
"file_path": "www.jixezky.com",
"file_name": "“后来,还是一名神秘武者强者,",
"real_name": "强者,手持一柄克罗合金战刀,化作一道流光,将黑冠金雕一刀劈成两半!",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
},
{
"id": "978",
"catalog_id": null,
"file_path": "www.sikcaum.com",
"file_name": "那一段视频,在网上传播的很广,",
"real_name": "很广,他也看到过",
"orderNo": null,
"suffix": null,
"file_type": null,
"edit_time": null
}]
}]
d.前台效果界面展示:
4.后台数据库分页的java代码
项目的后台采用Spring+SpringMvc+Mybatils框架,SpringMVC可以方便的接收来自前台的数据,,了解Java开发的开发人员可以知道,整个框架的MVC模式分明,包括controller、service、mapper等部分。
Controller部分代码如下:
@RequestMapping("/index")
@ResponseBody
public WebData index(int limit, int offset, int pageindex, int pageSize,String keyValue) {
WebData data = new WebData();
try {
List<Map<String, Object>> list = fileService.fileIndex(limit, offset, pageindex, pageSize,keyValue);
data = WebUtil.ListNormal(list);
} catch (Exception e) {
data = WebUtil.DescException(e.getMessage());
logger.log(Level.ERROR, "获取检索信息异常", e);
}
return data;
}
service部分代码如下:
public List<Map<String, Object>> fileIndex(int limit, int offset, int pageindex, int pageSize,String keyValue) {
List<Map<String, Object>> listAll = new ArrayList<>();
Map<String, Object> map = new HashMap<>();
int total = fileMapper.getTotalCount(keyValue);
int start = offset + 1;
int end = limit * pageindex;
if (end > total) {
end = total;
}
List<Map<String, Object>> list = fileMapper.fileIndex(keyValue,start,end);
map.put("rows", list);
map.put("total", total);
map.put("limit", limit);
map.put("offset", offset);
listAll.add(map);
return listAll;
}
mapper部分需要声明一个接口getTotalCount和fileIndex代码,在这不写了,直接贴一下sql语句:
<!-- 查询文件总数 -->
<select id="getTotalCount" resultType="Integer">
select count(*) from
NJ_FILE_CATALOG_PATH1 t
<if test="keyValue != null and keyValue != ''">
where t.real_name like CONCAT(CONCAT('%', #{keyValue}),
'%')
</if>
</select>
<!-- 文件分页查询 -->
<select id="fileIndex" resultType="com.item.entity.archives.Archives">
select * from (select
rownum as rowno,t.* from NJ_FILE_CATALOG_PATH1 t
where
<if test="keyValue != null and keyValue != ''">
t.real_name like CONCAT(CONCAT('%', #{keyValue}), '%') And
</if>
rownum <![CDATA[<]]>
= #{end}
) p where p.rowno <![CDATA[>]]>
= #{start}
</select>
这样的话,后台就实现了一个后台分页的过程,通过一定的处理和对前台数据的返回,跟前台联系起来进行分页,z在此,说明一下分页的三种常见形式:
第一种:采用前台分页,将数据全部交给前台,由于数据库存在10万条数据,如果使用这种方式肯定会使得前台压力大而崩溃;
第二种:后台查询所有的数据list,根据前台返回的pageindex、limit等进行sublist的截取,这种方式也是可行的,但是考虑到数据量如果太大也是太慢的;
第三种:通过前台获取页数、条件、每页条数等信息,在后台进行处理,用sql实现分页,这种方式不会直接获取所有的数据,而是根据页来得到数据库的数据,从而将压力降到最小,核心的两条sql语句上面也贴了出来(不一定是最合理的,但是是我想到的最好的了,希望路过的大神可以指教一下)。
5.过程中遇到的问题
a.Bootstrap table的method配置
根据自己的需求可以选择POST和get方式进行数据的请求,但是使用POST的时候,后台一直不可以,显示参数not present,原因可能是请求头需要配置一些,覆盖之前默认的请求头:
给table加一个这样的配置:
contentType : "application/x-www-form-urlencoded",
b.如何添加操作栏中的事件?
{
title : '操作',
align : 'center',
formatter : function(value, row,index) {
var d = '<a id="preview" class="btn btn-primary" style="height:26px;font-size:10px;" onclick="preview(\''
+ row.id
+ '\')"><i class=" fa fa-search"></i>预览</a> ';
return d;
},
events : {
'click #preview': function(e, value ,row ,index){
//方法,在此处写
alert(row.id);
}
}
}
c.返回值无法获取?
下列方法中,返回的是json数组的方式,json的格式已经放在了上面,res.rows[0].rows目的就是将rows里面的数据放在return里面:
function responseHandler(res) {
if (res) {
return {
"rows" : res.rows[0].rows,
"total" : res.rows[0].total
};
} else {
return {
"rows" : [],
"total" : 0
};
}
}
至此,本篇就结束了,只是作为最近学习的总结,如果有误,欢迎留言交流,多谢啦!!