在最近一个项目中,需要结合一堆条件查询并对查询的结果数据完成一个简单分页功能,可是做着做着,自己的思路越来越模糊,做到心态崩溃!!! 哈哈,特此花点时间重新总结,并从最简单的分页,然后向多条件查询分页慢慢过渡,或许有人觉得这个很简单(可以绕道啦,哈哈),却是对基础知识的一次学习过程。

  Demo地址:https://gitee.com/530521314/Partner.TreasureChest/tree/master/Pagination/

  本文地址:https://www.cnblogs.com/CKExp/p/9218904.html

一、环境介绍

  分页功能很多已有的很完美的插件或是第三方应用包都能够完美实现,我在此利用了一些前端插件来完成分页功能。

  前端的Bootstrap Paginator插件完成前端分页数字之类的切换展示;

  利用knockout.js插件完成分页数据的绑定;

  在后端,利用asp.net core mvc 完成分页信息的接收和处理工作。

二、简单分页

  完成对已有数据的分页功能,不带条件查询。

  首先,一上来便是完成数据绑定工作:

   bookList: ko.mapping.fromJS(@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model))),//展示数据
  pageEntity: ko.mapping.fromJS(@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(new PageRequestViewModel()))),//分页信息

    页面刚展示的时候得有分页数据吧,可以在当页面展示的时候,数据也带过来了,也可以页面展示后,再通过ajax去后台调用,我选择后者。

  在页面启动时,调用该函数完成初始化页面数据。

     getBookData: function () {
var pageEntity = ko.mapping.toJS(viewModel.pageEntity);
$.ajax({
url: '@Url.Action("SampleGetData")',
type: 'POST',
dataType: 'json',
data: pageEntity,
success: function (result) {
ko.mapping.fromJS(result.data, viewModel.bookList);
options.totalPages = result.totalCount > 0 ? result.totalCount % options.numberOfPages == 0 ?
result.totalCount / options.numberOfPages : (result.totalCount / options.numberOfPages) + 1 : 1;
$('#pagination').bootstrapPaginator(options);
}
});
}

   分页信息(当前页面,页面展示数据条数)带过去,后台根据分页信息完成数据查询,并获得总的记录条数用于前端页面计算总页数。

     [HttpPost]
public IActionResult SampleGetData(PageRequestViewModel pageEntity)
{
var bookList = PageDataSeed.GetPageDataList()
.Skip((pageEntity.PageIndex - ) * pageEntity.PageSize)
.Take(pageEntity.PageSize); var pageResultViewModel = new PageResultViewModel<Book>()
{
PageIndex = pageEntity.PageIndex,
PageSize = pageEntity.PageSize,
TotalCount = PageDataSeed.GetPageDataList().Count(),
Data = bookList
}; return Json(pageResultViewModel);
}

 根据分页信息查询也就搞定了,当点击底部的页面码的时候得改变当前分页信息,然后要切换当前分页信息所对应的数据出来,在Bootstrap paginator插件中,点击页面码有一个函数onPageClicked,点击具体的某一页后,根据参数page获得页面,改变当前展示的页面码数字,并对分页信息修改,然后再次调用ajax获得新数据。

     onPageClicked: function (event, originalEvent, type, page) {
options.currentPage = page;
viewModel.pageEntity.PageIndex = page;
viewModel.getBookData();
},

  至此,简单分页功能便搞定了,在此实现中,偏重于前端实现分页逻辑,后台只是取得相应的数据。

  

三、单条件查询分页

  复制一份简单分页后,改造下加入一个根据书名条件项,查询后完成分页功能。

  首先加入书名绑定,在此用了两个书名,第二个是有目的性的留着,也只是我的理解,条件查询后,如果底部展示有多页,那么我在点击每一页的时候,我的查询条件不能动吧,基于此考虑的。

     bookName: ko.observable(),
bookNameBackup: ko.observable(),

  数据查询部分改动不大,主要是把查询条件加入进来,因此只改动data参数即可。

     getBookData: function () {
var pageEntity = ko.mapping.toJS(viewModel.pageEntity);
$.ajax({
url: '@Url.Action("SingleQueryGetData")',
type: 'POST',
dataType: 'json',
data: {"pageEntity":pageEntity, "bookName":viewModel.bookName()},
success: function (result) {
ko.mapping.fromJS(result.data, viewModel.bookList);
options.totalPages = result.totalCount > 0 ? result.totalCount % options.numberOfPages == 0 ?
result.totalCount / options.numberOfPages : (result.totalCount / options.numberOfPages) + 1 : 1;
$('#pagination').bootstrapPaginator(options);
}
});
},

  前端Html部分加入单条件项,以书名为例,查询按钮绑定点击后的触发函数

     <div class="form-group">
<label for="bookName" class="col-sm-2 control-label">书名</label>
<div class="col-sm-2">
<input type="text" class="form-control" id="bookName" data-bind="value:bookName">
</div>
<button class="btn btn-primary col-sm-1" data-bind="click:queryBookList">查询</button>
</div>

  点击查询后执行函数,将当前页面重置为1,查询数据,并记录该次查询的查询条件。

   //查询
queryBookList: function () {
options.currentPage = 1;
viewModel.pageEntity.PageIndex = options.currentPage;
viewModel.getBookData();
viewModel.bookNameBackup(viewModel.bookName());//记录查询条件,分页点击时需要用到
}

  查询完毕,然后假设底部还存在很多页面码可以选择,当我们点击页面码的时候,因为查询条件仍然存在,我们点击后仍然会完成分页功能,但是!!!

  当把查询条件清空,比如在此demo中,把书名置空,此时不点查询按钮,而是直接点击页面码,那情况会如何呢,查询条件已经没了;

  或是说查询条件为空时,输入查询条件,不点查询按钮,直接点击页面码;

  这都是不合理的情形,点击页面码的时候肯定得保证原查询条件的存在,至少我是这么想的,或许您有更好的建议,请告诉我,十分感谢。这也就是我在之前设置了一个监控对象bookNameBackup的原因,备份查询条件,防止点击页码切换时查询条件变更的情形。

  前端已经改好了,然后进入后端来改一下,先对条件判空处理,然后执行相应的逻辑。

     [HttpPost]
public IActionResult SingleQueryGetData(PageRequestViewModel pageEntity, string bookName)
{
IEnumerable<Book> bookList = PageDataSeed.GetPageDataList();
PageResultViewModel<Book> pageResultViewModel = null; if (!string.IsNullOrEmpty(bookName))
bookList = bookList.Where(b => b.BookName.Contains(bookName)); var books = bookList.Skip((pageEntity.PageIndex - ) * pageEntity.PageSize)
.Take(pageEntity.PageSize); pageResultViewModel = new PageResultViewModel<Book>()
{
PageIndex = pageEntity.PageIndex,
PageSize = pageEntity.PageSize,
TotalCount = bookList.Count(),
Data = books
}; return Json(pageResultViewModel);
}

  单条件查询分页功能也就搞定了,查询和点击页面码所执行的逻辑是不一样的,虽然都调用到了最终的数据查询方法,但是对于条件的处理是不一样的。

  

四、多条件查询分页

  对单条件查询分页下多加入几个条件,进入到多条件查询,变化其实不大,只是为了方便管理如此多的查询条件,改成了以对象形式管理

  首先绑定查询对象信息,该对象中包括了三个查询条件,书名,作者,出版社,仍然设置一个备份对象,原因和单条件查询下是一样的。

     queryItemEntity: ko.mapping.fromJS(@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(new QueryItemViewModel()))),//查询条件信息
queryItemEntityBackup: ko.mapping.fromJS(@Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(new QueryItemViewModel()))),//查询条件信息备份

  页面的查询条件多了,通过queryItemEntity为前缀展示,也方便维护

     <div id="queryItem" class="form-horizontal">
<div class="form-group">
<label for="bookName" class="col-sm-2 control-label">书名</label>
<div class="col-sm-2">
<input type="text" class="form-control" id="bookName" data-bind="value:queryItemEntity.BookName">
</div>
<label for="author" class="col-sm-2 control-label">作者</label>
<div class="col-sm-2">
<input type="text" class="form-control" id="author" data-bind="value:queryItemEntity.Author">
</div>
<label for="press" class="col-sm-2 control-label">出版社</label>
<div class="col-sm-2">
<input type="text" class="form-control" id="press" data-bind="value:queryItemEntity.Press">
</div>
</div>
<button class="btn btn-primary" data-bind="click:queryBookList">查询</button>
</div>

  查询条件改动,也使得数据查询部分的条件改变了,将查询条件整体封装,而不是零散的传递,改动之处加入了第三行将ko上的查询条件信息转换为JS对象和改变了参数data的值。

   getBookData: function () {
var pageEntity = ko.mapping.toJS(viewModel.pageEntity);
var queryItemEntity = ko.mapping.toJS(viewModel.queryItemEntity); $.ajax({
url: '@Url.Action("MultipleQueryGetData")',
type: 'POST',
dataType: 'json',
data: { "pageEntity": pageEntity, "queryItemEntity": queryItemEntity},
success: function (result) {
ko.mapping.fromJS(result.data, viewModel.bookList);
options.totalPages = result.totalCount > 0 ? result.totalCount % options.numberOfPages == 0 ?
result.totalCount / options.numberOfPages : (result.totalCount / options.numberOfPages) + 1 : 1;
$('#pagination').bootstrapPaginator(options);
}
});
},

  点击按钮查询处的逻辑还是没有改变,仍然是查询记录并将查询条件备份,用于分页控件中页面码的点击函数。

     //查询
queryBookList: function () {
options.currentPage = 1;
viewModel.pageEntity.PageIndex = options.currentPage;
viewModel.getBookData();
ko.mapping.fromJS(viewModel.queryItemEntity, viewModel.queryItemEntityBackup);//记录查询条件,分页点击时需要用到
}

  对于前端来讲改动并不是很大,无非是将查询条件封装一下,同样后端的改动只是多个查询条件的过滤,依次比对三个查询条件是否为空,并挨个去完成查询的过滤。

     [HttpPost]
public IActionResult MultipleQueryGetData(PageRequestViewModel pageEntity, QueryItemViewModel queryItemEntity)
{
var bookList = PageDataSeed.GetPageDataList(); #region 条件过滤
if (!string.IsNullOrEmpty(queryItemEntity.BookName))
bookList = bookList.Where(b => b.BookName.Contains(queryItemEntity.BookName)).ToList();
if (!string.IsNullOrEmpty(queryItemEntity.Author))
bookList = bookList.Where(b => b.Author.Contains(queryItemEntity.Author)).ToList();
if (!string.IsNullOrEmpty(queryItemEntity.Press))
bookList = bookList.Where(b => b.Press.Contains(queryItemEntity.Press)).ToList();
#endregion var books = bookList.Skip((pageEntity.PageIndex - ) * pageEntity.PageSize).Take(pageEntity.PageSize); var pageResultViewModel = new PageResultViewModel<Book>()
{
PageIndex = pageEntity.PageIndex,
PageSize = pageEntity.PageSize,
TotalCount = bookList.Count(),
Data = books
}; return Json(pageResultViewModel);
}

  多条件查询分页的效果展示

  

  至此,查询功能算是简单完成了,或许还有漏洞地方,没有发现,特别是逻辑漏洞,防不胜防,望多指教,感谢。

  设计一个小Demo一方面是对分页功能进行一下总结,以防自己若干天或是若干年后还需要,可以回来看看,一方面也是如果有需要的朋友可以加快编码和设计的过程。

  码云上存放Demo的地址:https://gitee.com/530521314/Partner.TreasureChest/tree/master/Pagination/

2018-6-24,望技术有成后能回来看见自己的脚步

  

利用Bootstrap Paginator插件和KnockoutJS完成分页功能的更多相关文章

  1. C#设计模式总结 C#设计模式(22)——访问者模式(Vistor Pattern) C#设计模式总结 .NET Core launch.json 简介 利用Bootstrap Paginator插件和knockout.js完成分页功能 图片在线裁剪和图片上传总结 循序渐进学.Net Core Web Api开发系列【2】:利用Swagger调试WebApi

    C#设计模式总结 一. 设计原则 使用设计模式的根本原因是适应变化,提高代码复用率,使软件更具有可维护性和可扩展性.并且,在进行设计的时候,也需要遵循以下几个原则:单一职责原则.开放封闭原则.里氏代替 ...

  2. 利用BootStrap Table插件实现自己的弹出框分页。

    参考链接1:    官网:http://bootstrap-table.wenzhixin.net.cn/zh-cn/home/        开始使用:http://bootstrap-table. ...

  3. 传统方式和插件方式 分别实现 分页 功能 pageHelper 插件

    实现分页  这里提供两种方式  一种是传统的分页方式  一种是基于pageHelper插件 实现的分类     推荐使用后者 前者是一般开发的方式   思路  先手动创建一个 pageUtil 工具 ...

  4. Bootstrap Paginator分页插件+ajax 实现动态无刷新分页

    之前做分页想过做淘宝的那个,但是因为是后台要求不高,就Bootstrap Paginator插件感觉还蛮容易上手,所以就选了它. Bootstrap Paginator分页插件下载地址: Downlo ...

  5. Django 实现分页功能(django 2.2.7 python 3.7.5 )

    Django 自带名为 Paginator 的分页工具, 方便我们实现分页功能.本文就讲解如何使用 Paginator 实现分页功能. 一. Paginator Paginator 类的作用是将我们需 ...

  6. bootstrap分页插件--Bootstrap Paginator的使用&AJAX版备份(可单独使用)

    html部分: <ul class="pagination"></ul> <!--bootstrap3版本用ul包裹--> <div cl ...

  7. Bootstrap Paginator 分页插件参数介绍及使用

    Bootstrap Paginator是一款基于Bootstrap的js分页插件,功能很丰富,个人觉得这款插件已经无可挑剔了.它提供了一系列的参数用来支持用户的定制,提供了公共的方法可随时获得插件状态 ...

  8. Bootstrap Paginator分页插件的使用

    今天,我为大家带来的一款做得非常优秀的分页插件BootStrap Paginator,他是一款js插件,由于本人也是才刚刚搞出来的,所以暂时对它也不是特别了解,只能大楖告诉大家怎么使用.我这里使用的是 ...

  9. Bootstrap Paginator分页插件

    Bootstrap Paginator分页插件使用示例 最近做的asp.netMVC项目中需要对数据列表进行分类,这个本来就是基于bootstrap开发的后台,因此也就想着bootstrap是否有分页 ...

随机推荐

  1. 接口测试返回的json文件中字符串是乱序

    问题描述 接口测试中post方式匹配返回信息时显示不匹配, 但是statuscode明明是200, 而且用postman /restclient等工具测出来也是没问题的. 根本原因 封装了这么个方法来 ...

  2. markdown箭头的处理

    转自:https://blog.csdn.net/m0_37167788/article/details/78603307 MarkDown - Latex符号(箭头)的整理 标签: markdown ...

  3. 【线段树】Bzoj1798 [AHOI2009] 维护序列

    Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2 ...

  4. bzoj 3551 kruskal重构树dfs序上的主席树

    强制在线 kruskal重构树,每两点间的最大边权即为其lca的点权. 倍增找,dfs序对应区间搞主席树 #include<cstdio> #include<cstring> ...

  5. keras实现简单性别识别(二分类问题)

    keras实现简单性别识别(二分类问题) 第一步:准备好需要的库 tensorflow  1.4.0 h5py 2.7.0 hdf5 1.8.15.1 Keras     2.0.8 opencv-p ...

  6. 浅谈URL跳转与Webview安全

    学习信息安全技术的过程中,用开阔的眼光看待安全问题会得到不同的结论. 在一次测试中我用Burpsuite搜索了关键词url找到了某处url,测试一下发现waf拦截了指向外域的请求,于是开始尝试绕过.第 ...

  7. C# 高性能 TCP 服务的多种实现方式

    哎~~ 想想大部分园友应该对 "高性能" 字样更感兴趣,为了吸引眼球所以标题中一定要突出,其实我更喜欢的标题是<猴赛雷,C# 编写 TCP 服务的花样姿势!>. 本篇文 ...

  8. SSRS报表服务随笔(rdl报表服务)-报表参数

    上一篇我们说了创建一个简单的显示报表,但在实际工作中,我们有很多要带条件的报表 现在先认识一下报表数据,首次打开SSDT,报表数据在窗口的左侧,要是找不到了,没关系,在工具栏-视图-最下面的报表数据 ...

  9. 基于ITextSharp插件在ASP.NET MVC中将图表导出为PDF

    样本: 在这个示例中,我们使用的是微软给我们提供的数据库,也就是家喻户晓的Northwind数据库.要下载Microsoft的免费样本Northwind数据库,您需要访问以下URL.下载Northwi ...

  10. Jenkins 集成 SonarQube Scanner

    1.   安装Jenkins 下载安装包,这里我们下载war包 https://jenkins.io/download/ 运行jenkins.war的方式有两种: 第一种:将其放到tomcat中运行( ...