背景介绍
说实话,前端一直是我的薄弱项,每次新需求的最大难点就是前端技术的攻克,不仅仅是前端技术的框架繁多,菜也是原罪
这次的需求是在后台调用另外一个系统接口,将返回的数据通过表格的形式展示在页面上,要做一个表格,那选择可真的就太多了,前端有很多优秀的组件,如easyui-edatagrid,jQuery-Grid等等,但是想到我毕竟用的前端框架都是bootstrap,看一下有不有bootstrap的table插件,一查还有真有一个bootstrap-table,真香,最后下面就是使用bootstrap-table做的页面,效果图如下(已完成页面)
上图可以看到这个页面有一个搜索框,很明显这个不是bootstrap-table自带的搜索,大部分也不会用它自带的搜索栏。然后是表格里面的的数据,到最后的分页信息。到这里细看你会觉得数据不对劲啊,页面最多展示了7条数据,怎么下面的分页信息一共4页,还显示的是1到10条记录。其实通过百度就知道 boostrap-table 通过js获取到的数据格式为 {total:7,rows[]}这样的,total就是每次返回的总数据条数,rows就是表格展示的数据,通过这两个数据页面就展示的非常完美,也不会有数据奇怪的地方,但给你们看一下他们给的数据格式
下面是三方系统给的数据格式
{
"searchResult": [{
"klgId": "24",
"klgName": "测试1145",
"docVersion": "1",
"catgoryName": "专席服务",
"catgoryId": "1",
"title": "测试1145",
"abstrac": "",
"keywords": "测试1145",
"areaId": ",1-0,330000000000-1,170000001000-1,310000000000-1,260000000000-1,",
"areaName": "/广西省/崇左/北海/河池/",
"faFullPath": "",
"fjcontent": "噶he太极图软件同居任何人同居人同仁堂和",
"categoryPath": "/专席服务/",
"createTime": "2020-08-04 00:00:00",
"visitCount": "0",
"url": null
}, {
"klgId": "25",
"klgName": "高级5G手机售卖",
"docVersion": "1",
"catgoryName": "专席服务",
"catgoryId": "1",
"title": "高级5G手机售卖",
"abstrac": "",
"keywords": "5G",
"areaId": ",1-0,330000000000-1,170000001000-1,310000000000-1",
"areaName": "/广西省/崇左/北海",
"faFullPath": "",
"fjcontent": "数据库科技换个地方已投入的润滑油干涉法投入和暗访时退役犹太人",
"categoryPath": "/专席服务/",
"createTime": "2020-08-04 15:40:22",
"visitCount": "0",
"url": null
}],
"flag": true,
"searchtype": "1",
"searchMap": {
"SEARCH_TIME": "0.033",
"RESULT_COUNT": "2",
"PAGE_COUNT": "1",
"countResult": 2
}
}
拿到这个数据的时候我大致分析了一下啊,这个json里面各个组成部分还是比较容易懂得searchResult就是要展示得数据rows,searchMap就是一些查询时间,数据量,页码等数据。等等,页码等数据。淦,直接给我总条数不行吗?我需要total啊,这里一个PAGE_COUNT(总页数)说实话让我得工作量大了一点,接下来会分析到这个问题
1. 后台代码编写
首先就在controller写一个简单的接口,该接口的作用就是接收前端请求参数,然后通过httpClient的get请求获得数据,最后再重新组装一下自己需要的数据,返回json格式的数据就可以了。
@RequestMapping(value = "searchMethod", method = RequestMethod.GET)
@ResponseBody
public JSONObject searchMethod(String klgName, String rows, String page, HttpServletRequest request, HttpServletResponse response){
// 因为前台可能没有传排序字段 这里如果为空 默认按照创建时间字段进行排序
String sort = null == request.getParameter("sort") ? "createTime": request.getParameter("sort");
String sortOrder = request.getParameter("sortOrder");
Map<String,String> params = new HashMap<>();
// 组装请求参数
params.put("area_id","1");
params.put("library_id","1");
params.put("klgName", klgName);
params.put("pageSize", rows);
params.put("pageIndex", page);
params.put("category_path_id","");
params.put("sort", sort + " " + sortOrder);
HttpUtil httpUtil = new HttpUtil();
JSONObject woJson = new JSONObject();
String url = oaNoticeDao.getApiUrlByName("searchMethod");
JSONObject rtnJson = new JSONObject();
try {
String result = httpUtil.get(url,params);
JSONObject rtnJson1 = JSONObject.fromObject(result);
JSONObject jsonObject = rtnJson1.getJSONObject("searchMap");
if (rtnJson1.getBoolean("flag")){
// total 和 rows 是bootstrap需要的数据格式
rtnJson.put("total",jsonObject.getInt("countResult"));
rtnJson.put("rows",rtnJson1.getJSONArray("searchResult"));
//这里的pageTotal是我自定义的一个数据
rtnJson.put("pageTotal",jsonObject.getInt("PAGE_COUNT"));
}
} catch (Exception e) {
e.printStackTrace();
}
return rtnJson;
}
2. 前端代码
下面就是简单的前端完整代码,有些就不详细解释,只介绍一下需要注意的地方
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ include file="/WEB-INF/views/include/taglib.jsp" %>
<html>
<head>
<style>
/* 因为bootstrapjs版本过低 导致bootstarp-table样式问题
* 在不影响版本的情况下添加了下面的样式
*/
/* 下面两个样式是设置分页的*/
.float-left { float: left !important; }
.float-right { float: right !important; }
/* 这个样式是设置分页的选择按钮样式*/
.dropdown-item {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
</style>
<link rel="stylesheet" type="text/css" href="${ctxStatic}/bootstrap/table/bootstrap-table.css"/>
<script src="${ctxStatic}/bootstrap/table/bootstrap-table.js" type="text/javascript"></script>
<script src="${ctxStatic}/bootstrap/table/locale/bootstrap-table-zh-CN.js" type="text/javascript"></script>
<title>知识库搜索</title>
<meta name="decorator" content="default"/>
<%@include file="/WEB-INF/views/include/treetable.jsp" %>
<script type="text/javascript">
$(function () {
InitMainTable();//.初始化Table
});
function searchData() {
var queryUrl = '${ctx}/oa/aipos/searchMethod';
// $('#tableL01').bootstrapTable('destroy');
$("#contentTable").bootstrapTable('refresh',{
url: queryUrl,
method: 'GET',
pagination: true,
pageSize: 10,
pageNumber: 1,
sidePagination: "server",
queryParamsType: "limit",
queryParams : function (params) {
//这里的键的名字和控制器的变量名必须一致,这边改动,控制器也需要改成一样的
var temp = {
rows: params.limit, //页面大小
page: (params.offset / params.limit) + 1, //页码
sort: params.sort, //排序列名
sortOrder: params.order, //排位命令(desc,asc)
klgName: $("#klgName").val()
};
return temp;
}
})
}
var $table;
//初始化bootstrap-table的内容
function InitMainTable () {
//记录页面bootstrap-table全局变量$table,方便应用
var queryUrl = '${ctx}/oa/aipos/searchMethod',
$table = $('#contentTable').bootstrapTable({
url: queryUrl, //请求后台的URL(*)
method: 'GET', //请求方式(*)
toolbar: '#toolbar', //工具按钮用哪个容器
striped: true, //是否显示行间隔色
cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*)
sortable: true, //是否启用排序
sortOrder: "asc", //排序方式
sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页,并记录
pageSize: 10, //每页的记录行数(*)
pageList: [10, 20], //可供选择的每页的行数(*)
search: false, //是否显示表格搜索
strictSearch: true,
minimumCountColumns: 2, //最少允许的列数
clickToSelect: true, //是否启用点击选中行
paginationHAlign: "right",
paginationPreText: "上一页",
paginationNextText: "下一页",
onlyInfoPagination:false,
uniqueId: "klgId",
smartDisplay:true, //每一行的唯一标识,一般为主键列
//得到查询的参数
queryParams : function (params) {
//这里的键的名字和控制器的变量名必须一致,这边改动,控制器也需要改成一样的
var temp = {
rows: params.limit, //页面大小
page: (params.offset / params.limit) + 1, //页码
sort: params.sort, //排序列名
sortOrder: params.order, //排位命令(desc,asc)
klgName: $("#klgName").val()
};
return temp;
},
columns: [{
field: 'title',
title: '标题',
sortable: true,
formatter:function (value,item,a) {
return "<a href='"+item.url+"' target='_blank'>"+value+"</a>";
}
}, {
field: 'fjcontent',
title: '内容'
}, {
field: 'areaName',
title: '发布区域'
}, {
field: 'createTime',
title: '创建时间',
sortable: true
}, {
field: 'visitCount',
title: '浏览量'
}],
onLoadSuccess: function () {
},
onLoadError: function () {
$.messager.alert("数据加载失败", result["msg"]);
},
// 下面是重写了分页信息方法 其中 pageTotal 参数是修改了 bootstrap-table.js 源码里面的增加的
formatShowingRows: function (pageFrom, pageTo, totalRows, totalNotFiltered, pageTotal) {
if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
return "显示第 ".concat("1", " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录(从 ").concat(totalNotFiltered, " 总记录中过滤)");
}
// return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录");
return "显示第 ".concat("1", " 到第 ").concat(pageTo, " 条记录,总共 ").concat(pageTotal, " 页");
}
});
}
</script>
</head>
<body>
<div id="searchForm" class="breadcrumb form-search">
<div>
<label>搜索词:</label><input id="klgName" name="klgName" type="text" maxlength="20"
class="input-medium"/>
<input id="btnSubmit" class="btn btn-primary" onclick="searchData()" value="查询"/>
</div>
</div>
<table id="contentTable" class="table table-striped table-bordered table-hover">
</table>
</body>
</html>
1) js 和 css的引用
要用到bootstrap.css,bootstrap.js,bootstrap-table.css,bootstrap-table.js,bootstrap-table-zh-CN.js依次引入就可以了,不依次引入有可能什么js报错啊,某个变量没定以之类的
<link rel="stylesheet" type="text/css" href="${ctxStatic}/bootstrap/table/bootstrap.css"/>
<link rel="stylesheet" type="text/css" href="${ctxStatic}/bootstrap/table/bootstrap-table.css"/>
<script src="${ctxStatic}/bootstrap/table/bootstrap.js" type="text/javascript"></script>
<script src="${ctxStatic}/bootstrap/table/bootstrap-table.js" type="text/javascript"></script>
<script src="${ctxStatic}/bootstrap/table/locale/bootstrap-table-zh-CN.js" type="text/javascript"></script>
2)页面初始化boostrap-tale并设置
下面的js首先就是初始化了boostrap-table的对象,里面设置了各个参数,每个参数都有不同的作用,因为我是请求的服务端数据,所以比较重要的是sidePagination: "server"这个设置
<script type="text/javascript">
$(function () {
InitMainTable();//.初始化Table
});
var $table;
//初始化bootstrap-table的内容
function InitMainTable () {
//记录页面bootstrap-table全局变量$table,方便应用
var queryUrl = '${ctx}/oa/aipos/searchMethod',
$table = $('#contentTable').bootstrapTable({
url: queryUrl, //请求后台的URL(*)
method: 'GET', //请求方式(*)
toolbar: '#toolbar', //工具按钮用哪个容器
striped: true, //是否显示行间隔色
cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
pagination: true, //是否显示分页(*)
sortable: true, //是否启用排序
sortOrder: "asc", //排序方式
sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*)
pageNumber: 1, //初始化加载第一页,默认第一页,并记录
pageSize: 10, //每页的记录行数(*)
pageList: [10, 20], //可供选择的每页的行数(*)
search: false, //是否显示表格搜索
strictSearch: true,
minimumCountColumns: 2, //最少允许的列数
clickToSelect: true, //是否启用点击选中行
paginationHAlign: "right",
paginationPreText: "上一页",
paginationNextText: "下一页",
onlyInfoPagination:false,
uniqueId: "klgId", //每一行的唯一标识,一般为主键列
smartDisplay:true,
// 返回页面的参数作为后台请求的参数
queryParams : function (params) {
var temp = {
rows: params.limit, //页面大小
page: (params.offset / params.limit) + 1, //页码
sort: params.sort, //排序列名
sortOrder: params.order, //排位命令(desc,asc)
klgName: $("#klgName").val() // 获取的是查询框的值
};
return temp;
},
columns: [{
field: 'title',
title: '标题',
sortable: true,
formatter:function (value,item,a) {
return "<a href='"+item.url+"' target='_blank'>"+value+"</a>";
}
}, {
field: 'fjcontent',
title: '内容'
}, {
field: 'areaName',
title: '发布区域'
}, {
field: 'createTime',
title: '创建时间',
sortable: true
}, {
field: 'visitCount',
title: '浏览量'
}],
onLoadSuccess: function () {
},
onLoadError: function () {
$.messager.alert("数据加载失败", result["msg"]);
},
// 下面是重写了分页信息方法 其中 pageTotal 参数是修改了 bootstrap-table.js 源码里面的增加的
formatShowingRows: function (pageFrom, pageTo, totalRows, totalNotFiltered, pageTotal) {
if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
return "显示第 ".concat("1", " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录(从 ").concat(totalNotFiltered, " 总记录中过滤)");
}
// return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录");
return "显示第 ".concat("1", " 到第 ").concat(pageTo, " 条记录,总共 ").concat(pageTotal, " 页");
}
});
}
</script>
其实使用bootstrap-table就这么简单,下面我就是记录一下我遇到的问题,这个就比较有趣了,遇到此问题的朋友可以借鉴一下
问题总结
1. 分页信息与分页栏不在一个水平,并且分页下拉框格式不对
下面这个图片,我们就可以看到不仅分页信息和分页栏不在同一个水平上,而且分页显示最大数的下拉框的格式也不对,正常的效果应该是最上面那张最终的效果图,在同一个水平上
当时我还以为是css或者js什么的没引入进来,但是百度了一下,他们也是这样引入的啊,突然怀疑是版本问题,因为这个项目还是比较以前的了,bootstrap才2.3.1,而bootstrap-table是我刚刚才从官网上下的,感觉是版本差别太大。于是就将bootstrap.js换成最新版本试一试。
果不其然,换了最新的bootstrap之后的样式就正常了,那就初步定位了是bootstrap版本问题。但是非必要情况下尽量不要替换库版本,所以我们就针对分页信息进行比对,看新版本和老版本的样式有什么区别,最后得到如下的css样式,加上下面这个样式,就变成最上面那个图得效果了。
<style>
/* 因为bootstrapjs版本过低 导致bootstarp-table样式问题
* 在不影响版本的情况下添加了下面的样式
*/
/* 下面两个样式是设置分页的*/
.float-left { float: left !important; }
.float-right { float: right !important; }
/* 这个样式是设置分页的选择按钮样式*/
.dropdown-item {
display: block;
padding: 0.25rem 1.5rem;
color: #212529;
}
</style>
2. 当数据少于当前页最大数得时候没有分页栏
可以看到当只有7条数据的时候,右下角没有分页可以选择的
这种当时我还以为同样是版本问题嘞,但是我都换成了最新的版本之后依然没有分页信息,那就要从另外一方面入手了,直接看源码吧,首先通过在js中初始化table的时候就可以知道 pagination是代表分页的意思
下面就全是 bootstrap-table.js 源码的解析或者修改了 ,主要是为了分析部分问题和自定义分页栏
那我们就去boostrap-table.js 里面去找关于这个pagination的方法,还真找到了一个方法,但是这个方法代码太多了,我就不全部贴出来了,我就贴我们分析的代码
可以看到下面这个initPagination方法里面有这部分代码,当 this.totalPages <= 1 总数小于等于1的时候就会把右下角的分页栏给hide了,那就解释的通了,只要我给的 total 够多,totalPages 足够大 ,那就会显示
{
key: "initPagination",
value: function initPagination() {
var _this6 = this;
var opts = this.options;
..........
// 省略代码
..........
if (this.totalPages <= 1) {
this.$pagination.find('div.pagination').hide();
}
if (opts.smartDisplay) {
if (pageList.length < 2 || opts.totalRows <= pageList[0]) {
this.$pagination.find('span.page-list').hide();
}
} // when data is empty, hide the pagination
..........
}
}
那我们说干就干,我直接把后台数据的total改成14,然后一看,果然就出来了,虽然面板上只显示了7条数据,但是丝毫不影响分页的信息展示啊,可以,问题解决,同时也为下面问题的解决方案埋下了伏笔
3. 自定义分页信息
这里说复杂也复杂,说不复杂看懂了一下就知道了,先说一下自定义分页场景
正常的分页信息就是下面这样的
但是有些人想展示什么 查询时间啊,统计某个数据啊,显示三方系统信息等等,就需要自己去自定义修改
这里因为后台数据只给了展示的数据rows,还有rows的条数,以及总页数,其实正常的给我rows和总条数total就可以了,我要,他不给,只能自己解决
所以这里我就需要把 总共 14条记录 ----->>>>> 总共 2 页数据 因为我这里得到的是当前返回记录条数,不能算作总数,也不知道有多少条,用当前页最大数 * 总页数 也不太严谨
所以修改的地方有两个 一个是显示的记录数改为总页数 然后是分页栏根据后台总页数显示多少页
这里也是查阅了一些资料,但是资料都比较老了,只能大致借鉴一下,下面就是我最终的解决结果
我们在 下面这个变量里面加上我们的自定义参数 pageTotalField: ‘pageTotal’ 用于接收后台的 总页数
// 只截取了一部分 主要是为了体现我自定义参数添加的位置
var DEFAULTS = {
totalField: 'total',
totalNotFilteredField: 'totalNotFiltered',
dataField: 'rows',
pageTotalField: 'pageTotal', // 自定义的参数 方便后面获得后台返回的数据
footerField: 'footer',
pagination: false,
paginationParts: ['pageInfo', 'pageSize', 'pageList'],
showExtendedPagination: false,
paginationLoop: true,
sidePagination: 'client'
}
源码中下面这段是 数据加载 load 方法,详情看我得注释
{
key: "load",
value: function load(_data) {
var fixedScroll = false;
var data = _data; // #431: support pagination
// 其他得不看 看下面这里得赋值 当我们给bootstrap得属性为 sidePagination: "server" 就会进入下面得判断
if (this.options.pagination && this.options.sidePagination === 'server') {
// 这里终于能能知道 totalRows 和 totalNotFiltered 得值是怎么来了吧
this.options.totalRows = data[this.options.totalField];
this.options.totalNotFiltered = data[this.options.totalNotFilteredField];
// 既然如此 我们只用将后台需要得总页数的数据赋值一下就可以 后面就可以直接通过 this.options.pageTotal 拿到总页数了
// 这里的this.options.pageTotalField是default中我自定义变量的值pageTotalField: 'pageTotal',
this.options.pageTotal = data[this.options.pageTotalField]; // 等同于 data['pageTotal'] 取值
this.footerData = data[this.options.footerField] ? [data[this.options.footerField]] : undefined;
}
fixedScroll = data.fixedScroll;
data = Array.isArray(data) ? data : data[this.options.dataField];
this.initData(data);
this.initSearch();
this.initPagination();
this.initBody(fixedScroll);
}
}
数据拿到了,并且已经在 this.options 里面了,怎么用,在哪里用嘞?直接全局搜索 “条记录,总共” 然后可以看到bootstrap-table-zh-CN.min.js有这方面的代码
formatShowingRows:function(t,n,r,e){
return void 0!==e&&e>0&&e>r?"显示第 ".concat(t," 到第 ").concat(n," 条记录,总共 ").concat(r," 条记录(从 ").concat(e," 总记录中过滤)"):"显示第 ".concat(t," 到第 ").concat(n," 条记录,总共 ").concat(r," 条记录")
}
对应bootstrap-table-zh-CN.js 那就是 下面这个样子了,是不是一下就清晰了
formatShowingRows: function formatShowingRows(pageFrom, pageTo, totalRows, totalNotFiltered) {
if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
return "\u663E\u793A\u7B2C ".concat(pageFrom, " \u5230\u7B2C ").concat(pageTo, " \u6761\u8BB0\u5F55\uFF0C\u603B\u5171 ").concat(totalRows, " \u6761\u8BB0\u5F55\uFF08\u4ECE ").concat(totalNotFiltered, " \u603B\u8BB0\u5F55\u4E2D\u8FC7\u6EE4\uFF09");
}
return "\u663E\u793A\u7B2C ".concat(pageFrom, " \u5230\u7B2C ").concat(pageTo, " \u6761\u8BB0\u5F55\uFF0C\u603B\u5171 ").concat(totalRows, " \u6761\u8BB0\u5F55");
}
然后用 formatShowingRows 在bootstrap-table.js 里面搜索一下,可以看到下面这段代码,依然是initPagination 方法里面,然后调用了上面的这个方法
{
key: "initPagination",
value: function initPagination() {
var _this6 = this;
var opts = this.options;
..........
// 省略代码
..........
if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort')) {
var paginationInfo = this.paginationParts.includes('pageInfoShort') ? opts.formatDetailPagination(opts.totalRows) : opts.formatShowingRows(this.pageFrom, this.pageTo, opts.totalRows, opts.totalNotFiltered);
html.push("<span class=\"pagination-info\">\n ".concat(paginationInfo, "\n </span>"));
}
..........
}
}
所以修改就变得很简单了,我们只用在自己页面的js里面重写formatShowingRows方法,自己想怎么拼怎么拼
formatShowingRows: function (pageFrom, pageTo, totalRows, totalNotFiltered, pageTotal) {
if (totalNotFiltered !== undefined && totalNotFiltered > 0 && totalNotFiltered > totalRows) {
return "显示第 ".concat("1", " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录(从 ").concat(totalNotFiltered, " 总记录中过滤)");
}
// return "显示第 ".concat(pageFrom, " 到第 ").concat(pageTo, " 条记录,总共 ").concat(totalRows, " 条记录");
return "显示第 ".concat("1", " 到第 ").concat(pageTo, " 条记录,总共 ").concat(pageTotal, " 页");
}
然后再bootstap-table.js里面的这段代码里面加上自己的参数 opts.pageTotal 就可以了
{
key: "initPagination",
value: function initPagination() {
var _this6 = this;
var opts = this.options;
..........
// 省略代码
..........
if (this.paginationParts.includes('pageInfo') || this.paginationParts.includes('pageInfoShort')) {
var paginationInfo = this.paginationParts.includes('pageInfoShort') ? opts.formatDetailPagination(opts.totalRows) : opts.formatShowingRows(this.pageFrom, this.pageTo, opts.totalRows, opts.totalNotFiltered, opts.pageTotal);
html.push("<span class=\"pagination-info\">\n ".concat(paginationInfo, "\n </span>"));
}
..........
}
}
于是就等到了如下的效果图
到这里离成功就差不多到一半了,左边的分页信息是正确的自定义信息,可是右边的分页信息还是有点不对劲,总共4页,可是只有两页供选择,于是我们可以分析分析这个展示数据怎么来的
这方面的代码在之前的 当数据少于当前页最大数得时候没有分页栏 这个问题的时候出现过,也是在这个方法里面,主要代码如下
我会通过部分注释来解释这部分代码以及我改动的代码
{
key: "initPagination",
value: function initPagination() {
var _this6 = this;
var opts = this.options;
..........
// 省略代码
..........
if (this.paginationParts.includes('pageList')) {
html.push("<div class=\"".concat(this.constants.classes.pull, "-").concat(opts.paginationHAlign, " pagination\">"), Utils.sprintf(this.constants.html.pagination[0], Utils.sprintf(' pagination-%s', opts.iconSize)), Utils.sprintf(this.constants.html.paginationItem, ' page-pre', opts.formatSRPaginationPreText(), opts.paginationPreText));
// 下面这段代码是我新增的,就是为了让默认的总页数 等于 我后台数据的总页数
this.totalPages = opts.pageTotal;
// 下面这些判断就是 初始化 分页信息 显示多少页 如果小于 5页 就显示 1,2,3,4,5 大于了就显示比如 2....6
if (this.totalPages < opts.paginationSuccessivelySize) {
from = 1;
to = this.totalPages;
} else {
from = opts.pageNumber - opts.paginationPagesBySide;
to = from + opts.paginationPagesBySide * 2;
}
if (opts.pageNumber < opts.paginationSuccessivelySize - 1) {
to = opts.paginationSuccessivelySize;
}
if (opts.paginationSuccessivelySize > this.totalPages - from) {
from = from - (opts.paginationSuccessivelySize - (this.totalPages - from)) + 1;
}
if (from < 1) {
from = 1;
}
if (to > this.totalPages) {
to = this.totalPages;
}
var middleSize = Math.round(opts.paginationPagesBySide / 2);
// 这个方法就是根据传参来返回每个页数的html
var pageItem = function pageItem(i) {
var classes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
return Utils.sprintf(_this6.constants.html.paginationItem, classes + (i === opts.pageNumber ? " ".concat(_this6.constants.classes.paginationActive) : ''), opts.formatSRPaginationPageText(i), i);
};
if (from > 1) {
var max = opts.paginationPagesBySide;
if (max >= from) max = from - 1;
for (i = 1; i <= max; i++) {
html.push(pageItem(i));
}
if (from - 1 === max + 1) {
i = from - 1;
html.push(pageItem(i));
} else {
if (from - 1 > max) {
if (from - opts.paginationPagesBySide * 2 > opts.paginationPagesBySide && opts.paginationUseIntermediate) {
i = Math.round((from - middleSize) / 2 + middleSize);
html.push(pageItem(i, ' page-intermediate'));
} else {
html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-first-separator disabled', '', '...'));
}
}
}
}
// 这个就是从开始到最大页数开始拼html代码了
for (i = from; i <= to; i++) {
html.push(pageItem(i));
}
if (this.totalPages > to) {
var min = this.totalPages - (opts.paginationPagesBySide - 1);
if (to >= min) min = to + 1;
if (to + 1 === min - 1) {
i = to + 1;
html.push(pageItem(i));
} else {
if (min > to + 1) {
if (this.totalPages - to > opts.paginationPagesBySide * 2 && opts.paginationUseIntermediate) {
i = Math.round((this.totalPages - middleSize - to) / 2 + to);
html.push(pageItem(i, ' page-intermediate'));
} else {
html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-last-separator disabled', '', '...'));
}
}
}
for (i = min; i <= this.totalPages; i++) {
html.push(pageItem(i));
}
}
html.push(Utils.sprintf(this.constants.html.paginationItem, ' page-next', opts.formatSRPaginationNextText(), opts.paginationNextText));
html.push(this.constants.html.pagination[1], '</div>');
}
..........
}
}
到此处修改之后,整个页面的效果如下了
看着没啥毛病,再次测试之后才发现,当点击第三页或者一直点下一页到第三页的时候都会回到第一页或者没反应
这种情况光看代码就太慢了,直接debug吧
首先可以看到当选择的页码的时候,li标签的class就会多一个active
我们再来分析一下这个方法,该方法就是返回对应页码的html代码
var pageItem = function pageItem(i) {
var classes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
return Utils.sprintf(_this6.constants.html.paginationItem, classes + (i === opts.pageNumber ? " ".concat(_this6.constants.classes.paginationActive) : ''), opts.formatSRPaginationPageText(i), i);
};
我们看这段代码(i === opts.pageNumber ? " ".concat(_this6.constants.classes.paginationActive) : '')
这里的意思是如果当前 i 等于 opts.pageNumber 那么就 为 " ".concat(_this6.constants.classes.paginationActive) 这里的就是 active属性
所以我们就看为什么我们点击第四页的时候这里的每个参数值
debug之后可以看到 不管 i 等于多少 , opts.pageNumber 一直等于 2
我们就需要弄清楚 opts.pageNumber 的值怎么来的,并且意义是什么
依然还是这个方法里面的代码,我们往上看,可以看到如下的这段代码
this.totalPages = 0;
if (opts.totalRows) {
if (opts.pageSize === opts.formatAllRows()) {
opts.pageSize = opts.totalRows;
allSelected = true;
}
this.totalPages = ~~((opts.totalRows - 1) / opts.pageSize) + 1;
opts.totalPages = this.totalPages;
}
if (this.totalPages > 0 && opts.pageNumber > this.totalPages) {
opts.pageNumber = this.totalPages;
}
本身的 opts.pageNumber 等于 4 ,就是我选择的页码的值 ,到了上面这段代码之后,通过一系列的判断赋值之后 就等于 2了,根本原因还是this.totalPages = ~~((opts.totalRows - 1) / opts.pageSize) + 1;
还是这里 ,我的总页数应该是取得后台的总页数值,而不是通过页面真实数据算出来的。所以这里修改一下 给 this.totalPages 重新赋值
下面就是我的修改代码,只增加了一句
this.totalPages = 0;
if (opts.totalRows) {
if (opts.pageSize === opts.formatAllRows()) {
opts.pageSize = opts.totalRows;
allSelected = true;
}
this.totalPages = ~~((opts.totalRows - 1) / opts.pageSize) + 1;
this.totalPages = opts.pageTotal; // 这里因为是根据后台返回的总页数来操作 所以要重新赋值
opts.totalPages = this.totalPages;
}
if (this.totalPages > 0 && opts.pageNumber > this.totalPages) {
opts.pageNumber = this.totalPages;
}
最后再测试一下,解决问题, 最终效果图如文章开篇页面图
希望能给大家带来帮助