自制Javascript分页插件,支持AJAX加载和URL带参跳转两种初始化方式,可用于同一页面的多个分页和不同页面的调用

11/25/2015来源:ASP.NET技巧人气:1673

闲话部分   

    最近闲着实在无聊,就做了点小东西练练手,由于原来一直在用aspNetPager进行分页,而且也进行了深度的定制与原有系统整合的也不错,不过毕竟是用别人的,想着看自己能试着做出来不能,后台的分页插件已经有比较成熟的了,那就自己试着写一个前台分页吧。

 

 

话不多说,先上效果图:

 

 

优点与缺点

来说说优缺点吧,首先AspNetPager是后台分页控件,所以在向客户端回传HTML文档之前生成HTML阶段 就会把分页代码生成完毕,然后回传,而JS是前端代码,就是HTML文档在服务器组织完毕往客户端传送完毕之后才登上舞台。基于上述的区别,很容易总结出下面的优缺点:

优点:

1,轻量级,引入JS即可,十分方便部署与使用。

2,与后台程序语言无关,可以在任何语言平台上使用。

3,减少服务器负担,减少传输成本,加快响应速度,改善用户体验。

4,前端代码没有被编译,方便维护和管理。

缺点:

1,不支持SEO优化。

2,需要单独编写接口。

 

 

基本思路

1,我们需要通过一些参数如:记录总条数(itemCount)、每页条数(pageSize)来计算总共可以分的页数(pageCount),itemCount需要通过请求数据来获取,而pageCoun则需要通过用户来指定。

 

2,我们需要知道当前是在第几页(currPage)。当页面首次加载的时候默认为1,用户也可以指定默认加载时处在第几页上。当翻页时就会获得一个新的currPage。

 

3,有了这些我们似乎是可以开始工作了,首页 尾页很好解决,首页页码永远为1,而尾页页码永远为pageCount,上一页 下一页也可以解决,上一页为 currPage-1 ,下一页为 currPage+1。似乎很完美,不过不要忘了,上一页页码为currPage-1只能是 在currPage>1的时候,而下一页页码为currPage+1则只能是在currPage<pageCount的时候,我想你一定知道为什么,所以在这里要判断一下。

 

4,通过currPage和pageSize,我们可以很轻松的计算出当前显示的记录为第几条~第几条,前面也获取到了pageCount,pageSize等数据,因此可以拼接字符串,来显示分页信息

 

信息显示例如:  共12条  第1/4页  第1~3条  3条/页

 

5,重头戏来了,对于中间页码部分的处理。简单处理的话很好办,从1到pageCount依次排列,似乎就可以了,但是不要忘了,假如你这个列表有几十页甚至上百页,那这样排列显然不够优雅,那么我们需要另外一个参数,那就是中间显示页码的个数(showPageCount),当页码很多的时候,最多只显示 2×showPageCount+1个页码。你一定会问,为什么是 2×showPageCount+1,而不是showPageCount。原因是我这里为了判断方便,showPageCount的含义为,当前页面左右两边出现的页码个数。

例如:总共有10页,当前页为5,showPageCount为2,

那么页码则显示为:  首页  上一页   3  4  5  6  7  下一页  尾页

意外情况:如果左边或者右边显示不够showPageCount的页码数量,为了保持页码显示量是一定的,则会从另外一侧补全。

例如:总共10也,当前页面为2,showPageCount为4,左侧只有1个页面可以显示,则从右侧补全,

页码显示为:  首页  上一页   1  2  3  4  5  6  7  8  9  下一页   尾页

 

6,再在最后设置一个 Input 和 A 标签用作转到指定页面功能。

 

7,到此为止,我们只需要把上面的各个步骤 分别拼接字符串 输出到页面上就OK了,但是,还有一个重要话题没有讨论,目前为止,我们只是实现了分页的结构,但是功能似乎还没有实现。实现功能有两种方式:

(1),给页码标签的 href 属性绑定对应的链接,后面跟参数如 href="Article.aspx?page=2" 点击之后带上页码参数2 去请求第二页的信息。我们在后台程序通过Request到page的值,给Repeater控件做相应的绑定也好,输出字符串也好,都可以实现功能。

(2),添加 onclick 属性,并绑定函数,通过函数做 Ajax 请求,通过响应的函数(可以是键值对,也可以是HTML字符串),来给替换当前页面上的列表,产生新的列表,同时分页的当前页也需要更换成对应的当前页,完成之后效果实现。

第一种很简单,在拼接字符串的时候,顺带这把 href  属性写了就完事,这里不做过多叙述,关键说第二种,由于采用了ajax 在翻页的时候做请求,拿到响应数据,改写列表容器,既然如此,那么我们页面首次加载获取pageCount的时候,也可以顺便把列表给绑定了。简单总结起来大致流程如下:

A:页面加载——收集请求参数和查询条件(currPage为1),ajax请求,拿到响应信息(至少包括 itemCount 和 列表信息),通过回调函数,用itemCount 计算分页的各项参数 生成分页,通过列表信息,生成列表,完成初次加载。

B:翻页事件——再次收集求情和查询条件(currPage为当前页码),ajax请求,拿到响应信息(至少包括 itemCount 和 列表信息),通过回调函数,用itemCount 计算分页的各项参数 拼接字符串改写分页容器内容,通过列表信息,改写列表容器内容,完成初次加载。

我们可以直观的发现,A事件和B事件,流程基本一致,唯一的区别就是 currPage的值不同,因此我们可以做一个类似于递归的方法(不算严格意义上的递归),我们写一个 Load() 函数来用作 列表和分页的首次加载,在容器值被改写过之后,需要给 页码的 onclick 事件绑定函数,此时我们绑用本身这个Load()函数,所以每次点击后仍然绑定的是Load()方法。这样一段代码,就可以在两个事件中重复使用了。

 

8,关于传参,刚才我们一直提到 手机请求参数和查询条件,例如:容器ID,列表所属分类ID,每页条数,URL格式等等。 那么我们究竟如何把参数传递到方法中去?想实现目的,以下几种方式都可以。

A:声明全局变量,在函数中调用,但是这种方式会造成大量的变量冗余,同时 Load()函数需要 传入大量的参数,如:Load(agrA,agrB , agrC , agrD , agrE , agrF ... ),不可取。

B : 传入Json字符串,通过键值对的方式传入参数,这种方法,虽说只有一个参数,但是在编写的时候过于繁琐,而且无法指定默认值,或者可选项,需要在JS中重新判断,不可取。

C : 如果说上面两个都PASS掉了,那么你一定知道接下来要做什么了,没错!javaScript是一门面向对象的语言,虽然经常被人们忽略,但是他是可以使用对象和面向对象的一些编程方式的,因此我们可以建立分页的实体类,然后每次调用的时候,new() 出来一个新的对象,这样既可以保证同一个页面有多个分页的时候互不冲突,同时又可以优雅地指定我们的属性值,还可以通过类似于构造函数的方式进行默认值的初始化。

 

 

调用方式

引入jquery、ruguoPager和CSS

1 <script src="js/jquery-1.11.1.min.js"></script>
2 <script src="js/ruguoPager-1.0.js"></script>
3 <link rel="stylesheet" href="css/ruguoPager.css">

 

编写html结构指定好ID:

<div class="ctn">
  <div class="news" name="pager1">
    <ul class="list" id="news_ul"></ul>
    <div class="box_height_1000px"></div>
    <div class="ruguoPager_red" id="pager1"></div>
  </div>
</div>

 

在HTML页面上加入script标签 指定对象参数 进行分页

 1 <script>
 2   var pager = new ruguoPager();
 3   pager.pagerType="ajax";
 4   pager.objName="pager";
 5   pager.pagerID="pager1";
 6   pager.listID="news_ul";
 7   pager.toPoint="pager1"
 8   pager.showPageSize=4;
 9   pager.pageSize=3;
10   pager.currPage=1;
11   pager.typeID=63;
12   pager.pagerUrl="news/list_{ruguo:pageNum}.html";
13   pager.itemStr="<li><a href='news/detail_{ruguo:id}.html'>{ruguo:title}</a>[{ruguo:datetime}]</li>";
14   pager.ajaxUrl="ajax/getArticleList.ashx";
15   ruguoPagerLoad(pager);
16 </script>

 

 

参数列表(参数名,参数含义,可选值,必须)

 pagerType  初始化类型 'ajax'  or  ' url'   
 objName  对象名  string  *
 pagerID  分页容器ID  string  *
 listID  列表容器ID  string  -
 currPage  当前页  int  
 pageSize  每页条数  int  
 itemCount  记录总条数  int  
 showPageSize  显示页码数  string  
 pagerUrl  分页路径格式  string  -
 typeID  列表类别ID  int  
 titLen  列表标题字数  int  
 itemStr  列表标题格式  string  
 ajaxUrl  ajax请求地址  string  *
 toPoint  锚点标记  string  
 isShowFirst  是否显示首页按钮  'always'  ,  'auto'  ,  'none'  
 isShowPReviousPage  是否显示上一页按钮  'always'  ,  'auto'  ,  'none'  
 isShowNextPage  是否显示下一页按钮  'always'  ,  'auto'  ,  'none'  
 isShowLastPage  是否显示尾页按钮  'always'  ,  'auto'  ,  'none'  
 isShowPages  是否显示页码按钮  'always'  ,  'auto_0'  ,  'auto_1'  ,  'none'  
 isShowGo  是否显示跳转  'always'  ,  'auto'  ,  'none'  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

总结

在编写插件的过程中,遇到了很多实际的问题,并一个一个的加以解决,得到了不少心得,在这里总结一下。

1,类的使用

    在写Javascript的时候,尤其是在Jquery被广泛使用知乎,我们往往会在页面中罗列一个接一个的函数, 但是有时候我们尝试着使用一下类,会使得代码变得更加优雅。在写这个插件之前,只知道JS可以写类,实例化对象,但是究竟怎么用,却从来没试过,甚至怎么定义一个类都不知道。通过本例,初步了解了JS中类的基本使用方式。

2,函数的重载

    在解决 Load() 函数重用问题上,我想使用重载,但是根据自己的猜想,试了一下没有成功,经过查资料发现正确的使用方式。在C#中我们知道,方法可以重载,要求方法名相同,返回类型或者形参类型、数量不同。然而针对于JS来说,是没有重载一说的,因为JS是若类型语言,在调用方法的时候,根本没有参数类型以及返回类型一说。虽然如此,好在参数个数还是可以检测到的,所以根据这一特点,可以进行模拟重载,但是注意并非真正重载。

3,全局变量

    在写插件时候,第一次实例化的对象,并把对象的各个属性通过AJAX传递,拿到了响应信息,完成了分页和列表的首次加载。当点击分页时候,需要再次执行同样的操作,因此需要再次进行实例化对象,这样一来方法就无法复用,意味着,页面上每多一个分页,就需要copy一份js用作不同的 在点击分页时候的实例化。所以我就在想,点击分页事件时候的对象,与第一次的对象不一样的仅仅只是当前页码而已,所以通过对象本身包含对象名的方式,在绑定分页事件方法时,把对象名当作参数放在了Load()方法中,并多了一个当前页参数,通过模拟重载 顺利完成Load()方法的复用。虽然JS没有非常严格的访问级别,但是我想写在文档流中的变量应该都是全局变量,在初次实例化时候的对象同样也是,所以绑定分页事件方法中的参数 应该是可以调用到 全局对象的,结果证明我的猜想完全正确。

4,ajax分页用户体验

    通过ajax分页时候会有一个问题,那就是点击分页之后,由于页面并不刷新或者跳转,而是直接修改了页面容器的内容,所以页面会保持在列表最下方不动,每次点击完分页,需要手动把网页拨回到最顶部,然后再慢慢往下翻着看,很麻烦,所以我做了一个本地描点,在初次实例化的时候需要传锚点ID,点击之后,返回到锚点处。
效果类似于腾讯新闻列表的效果:http://news.QQ.com/top_index.shtml

5,jquery绑定事件传参

    在写插件过程中,起初用到了需要往jquery绑定事件中传参,由于习惯了使用 例如 $("a").click(function(){ alert("hello world"); });这样的绑定方式,所以如何往click事件所执行的方法中传入参数一时间十分苦恼,后来经过查询,知道了可以使用 这样的方式进行传参:$("a").bind("click",{myValue:hello world},function(event){ alert(event.data.myValue) }); ,虽然后来有了更好的方式,无需传参了,但是也算是一个不小的收获吧。

6,当json遇上HTML

    json是我们网上常用的传递数据的格式,而且js可以很轻松的解析,但是由于json遇到html中的 尖括号(< >)会出现问题,无法正确返回,因此,我们需要响应数据的时候进行HTML编码,在回调函数中,对拿到的编码后的字符串进行反编码。另外顺带提一下,在使用eval()解析数据的时候最好里面再套上一个"("+data+")",原因是json中的大括号会影响js的结构。

 

 

存在的问题

1,代码重用部分,其实并没有把url与ajax的方式完全区分开,由于当使用url的时候,初次加载列表和 总页数 可以通过后台绑定出来,因此在点击分页的时候,就无需再次请求数据,仅仅进行前台的计算即可,可以减少一次请求。

2,代码写的比较乱,大伙凑合着看吧。

3,本人才疏学浅,写代码纯属业余兴趣爱好,还望跟各位大神多多学习,存在的问题或者是更好的解决方案,还请不吝赐教,帮助我完善插件,网上成熟的插件有很多,本人献丑不敢说分享劳动成果工,只能说在学习中遇到的问题拿来给暂时还没有遇到的人,少走一些弯路,同时满足一下自己小小的成就感,仅此而已。

 

代码与文章都是博主辛苦一点一点码出来的,请尊重博主辛勤劳动,欢迎转载,转载请注明出处,更多交流请关注 D调码农的笔记簿 http://www.cnblogs.com/webconfig

 

最后放出下载地址

相关文档下载:http://files.cnblogs.com/webconfig/ruguoPager.rar