实现滑动分页(微博分页方式)

  现在大家都在上微博,而微博的滑动分页引起了我的兴趣,于是自己模仿着做,以下是这段时间的成果(单纯实现,没有考虑到效率和其他细节问题)

  实现内容:以30条记录为一页,每页分三次显示,每当把滚动条拖动到离浏览器底部10px时就显示该页的其余部分,当该页数据全部显示完时就显示页码控件供用户跳转到其他页面。如果数据加载失败,显示重新加载连接,实现用户手动重新加载数据。

  页面代码Default.aspx:

 1 <head runat="server">
 2     <title>滑动分页</title>
 3     <style type="text/css">
 4         #divPaging{width:500px;margin:0 auto;text-align:right;display:none}
 5         #divLoading,#divReLoading{width:500px;margin:0 auto;text-align:center;display:none}
 6         #divReLoading a{text-decoration:none}
 7         #divReLoading a:hover{text-decoration:underline}
 8     </style>
 9 </head>
10 <body>
11     <form id="form1" runat="server">
12         <div style="border:solid 1px #888;width:500px;margin:0 auto" runat="server" id="div" enableviewstate="false">
13         </div>
14         <div id="divPaging">跳转到第<asp:DropDownList runat="server" ID="ddl" AutoPostBack="true" OnSelectedIndexChanged="ddl_OnSelectedIndexChanged"></asp:DropDownList>页</div>
15         <div id="divLoading">正在加载......</div>
16         <div id="divReLoading">加载失败,<a href="javascript:Reload()">重新加载</a>页面</div>
17     </form>
18 </body>
19 </html>

Javascript代码:

 1 function $(id) { return document.getElementById(id); }
 2     var ajax = new AjaxHasPool();
 3     var method = "get";
 4     var url = "Handler.ashx?";
 5     indexOfPage = 1;
 6     isLoading = false;
 7     function WhenScroll() {
 8         if (document.documentElement.scrollTop + document.documentElement.clientHeight > document.documentElement.scrollHeight - 10 && indexOfPage <= 2 && !isLoading) {
 9             $("divLoading").style.display = "block";
10             isLoading = true;
11             var pageIndex = $("<%=ddl.ClientID %>").options[$("<%=ddl.ClientID %>").selectedIndex].value;
12             ajax.Startup(null, url + "pageIndex=" + pageIndex + "&indexOfPage=" + indexOfPage, method, EP);
13         }
14     }
15 
16     function Reload() {
17         if (indexOfPage <= 2 && !isLoading) {
18             $("divLoading").style.display = "block";
19             $("divReLoading").style.display = "none";
20             isLoading = true;
21             var pageIndex = $("<%=ddl.ClientID %>").options[$("<%=ddl.ClientID %>").selectedIndex].value;
22             ajax.Startup(null, url + "pageIndex=" + pageIndex + "&indexOfPage=" + indexOfPage, method, EP);
23         }
24     }
25 
26     function EP(xmlObj) {
27         $("divLoading").style.display = "none";
28         if (xmlObj.responseText == "false") {
29             $("divReLoading").style.display = "block";
30         }
31         else {
32             if (indexOfPage == 2) {
33                 $("divPaging").style.display = "block";
34             }
35             else {
36                 $("divPaging").style.display = "none";
37             }
38 
39             $("div").innerHTML += xmlObj.responseText;
40             ++indexOfPage;
41         }
42         isLoading = false;
43     }
44 
45     document.documentElement.onscroll = WhenScroll;

说明:

  1.首先要实现监听拖动滚动条事件,那么就要订阅document.documentElement对象的onscroll事件。

      2.这里我实现的是当滚动条离达浏览器底部10px时就读取该页的其余部分,使用onscroll处理函数中的document.documentElement.scrollTop + document.documentElement.clientHeight > document.documentElement.scrollHeight - 10进行判断。document.documentElement.scrollTop表示浏览器垂直方向被卷去的长度,document.documentElement.clientHeight表示浏览器可视工作区的高度(区别于document.body.clientHeight表示内容高度,可能小于等于大于浏览器可视工作区的高度),document.documentElement.scrollHeight表示内容高度。

     3.indexOfPage用于说明请求的是当前页的第几部分数据,因只分3个部分,所以如果indexOfPage>2就表明当前页的数据已经加载完成了,无需加载。当然也可加载完全部数据后把document.documentElement.onscroll设为null,这样就一了百了了。

     4.isLoading用于确保数据加载的顺序,当一个加载未完成时不允许发起下一个加载请求。(这个要注意哦!!)

     5.这里的AjaxHasPool()是自己对ajax封装的函数,使用了简单的对象池,请求并发时效率有所提升(最近还没能抽出时间学jquery等框架,自己写一个勉强用着吧。。。)

后台代码Default.aspx.cs

 1 public partial class _Default : System.Web.UI.Page 
 2 {
 3     private XMLManager manager = null;
 4     private PagedDataSource pds = null;
 5 
 6     protected void Page_Load(object sender, EventArgs e)
 7     {
 8         
 9         manager = new XMLManager();
10         pds = new PagedDataSource();
11         pds.DataSource = manager.GetData(0, 0);
12         pds.AllowPaging = true;
13         pds.PageSize = 30;
14         if (!IsPostBack)
15         {
16             for (int i = 0; i < pds.PageCount; ++i)
17             {
18                 this.ddl.Items.Add(new ListItem(Convert.ToString(i + 1), Convert.ToString(i)));
19             }
20             this.ddl.SelectedIndex = 0;
21             pds.CurrentPageIndex = 0;
22             List<obj> list = manager.GetData(pds.FirstIndexInPage, 10);
23             StringBuilder sb = new StringBuilder();
24             foreach (obj item in list)
25             {
26                 sb.Append("<div style='height:100px;border-bottom:dotted 1px #322323'>");
27                 sb.Append(item.Content);
28                 sb.Append("&emsp;");
29                 sb.Append(item.User);
30                 sb.Append("</div>");
31             }
32             div.InnerHtml = sb.ToString();
33         }
34     }
35 
36     protected void ddl_OnSelectedIndexChanged(object sender, EventArgs e)
37     {
38         this.pds.CurrentPageIndex = this.ddl.SelectedIndex;
39         List<obj> list = manager.GetData(this.pds.FirstIndexInPage, 10);
40         StringBuilder sb = new StringBuilder();
41         foreach (obj item in list)
42         {
43             sb.Append("<div style='height:100px;border-bottom:dotted 1px #322323'>");
44             sb.Append(item.Content);
45             sb.Append("&emsp;");
46             sb.Append(item.User);
47             sb.Append("</div>");
48         }
49         this.div.InnerHtml = sb.ToString();
50     }
51 
52 }

说明:

  1.这里的数据源是xml文件,写了个XmlManager类来操作,代码就不贴上来了。   2.分页用System.Web.UI.WebControl下的PagedDataSource十分省心,但本次实现没有考虑效率问题所以出现重复操作xml文件的情况,实际项目中应避免哦!注意:用PagedDataSource进行分页要把其属性AllowPaging设为true,不然得不到分页效果。

  3.dropdownlist的选择更改事件是整个页面唯一一个使用非ajax实现的,目的是丢弃之前页面的全部,重新加载一个画面。这点对于我来说教训很大,之前刚学ajax时打算把网站的方方面面都异步处理,结果出现滥用的情况,是页面的javascript代码十分庞大,最后到测试期出现严重的显示问题并且无法找问题根源,这里也包括我对代码的管理等的问题。分清楚哪些地方需要使用ajax请求,那些地方刷新整个页面是十分重要的!!

ajax异步请求处理类Handler.ashx

 1 public class Handler : IHttpHandler {
 2 
 3     XMLManager manager = new XMLManager();
 4     
 5     public void ProcessRequest (HttpContext context) {
 6         context.Response.ContentType = "text/plain";
 7         int pageIndex;
 8         bool hasPageIndex = Int32.TryParse(context.Request.QueryString["pageIndex"], out pageIndex);
 9         int indexOfPage;
10         bool hasIndexOfPage = Int32.TryParse(context.Request.QueryString["indexOfPage"], out indexOfPage);
11         StringBuilder sb = new StringBuilder(200);
12         if (hasIndexOfPage && hasPageIndex)
13         {
14             PagedDataSource pds = new PagedDataSource();
15             XMLManager manager = new XMLManager();
16             pds.DataSource = manager.GetData(0, 0);
17             pds.CurrentPageIndex = pageIndex;
18             pds.PageSize = 30;
19             pds.AllowPaging = true;
20             int firstIndexOfPage = pds.FirstIndexInPage;
21             List<obj> list = manager.GetData(firstIndexOfPage + (10 * indexOfPage), 10);
22             foreach (obj item in list)
23             {
24                 sb.Append("<div style='height:100px;border-bottom:dotted 1px #322323'>");
25                 sb.Append(item.Content);
26                 sb.Append("&emsp;");
27                 sb.Append(item.User);
28                 sb.Append("</div>");
29             }
30         }
31         else
32             sb.Append("false");
33         context.Response.Write(sb.ToString());
34     }
35  
36     public bool IsReusable {
37         get {
38             return false;
39         }
40     }
41 
42 }

这里就是根据页码和页内索引获取数据,但有其他地方想分享一下:

  1.StringBuilder初始化时可以设定初始容量,这个初始容量对性能有一定的影响,加入输入的内容超过了这个容量,那么stringbuilder对象会扩容为原来容量的1两倍,而扩容会消耗一定的资源,所以设定一个大概的初始容量有利于性能的提高。

  2.一般讲string转化为int32、int64等数值类型时,我都会使用Int32.TryParse方法,就算转化失败都不会抛异常而是返回false,然后再进行具体的if else处理,要知道抛异常是耗资源的。

如有更好的实现方法和改进的方式,请大家指教^_^

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏dotnet & java

Bootstrap-3-Typeahead

是Bootstrap-3-Typeahead,不是Twitter open source的typeahead,两者用法有差异。外加如果配合原生的Bootstra...

21460
来自专栏大内老A

我所理解的Remoting(1):Marshaling & Activation[下篇]

在上面一片文章,我花了大量的文字来来描述了Remote Object如何通过Marshaling的过程从Server端所在的Application Domain...

23160
来自专栏码农阿宇

.Net Core中利用TPL(任务并行库)构建Pipeline处理Dataflow

在学习的过程中,看一些一线的技术文档很吃力,而且考虑到国内那些技术牛人英语都不差的,要向他们看齐,所以每天下班都在疯狂地背单词,博客有些日子没有更新了,见谅见谅...

26710
来自专栏林德熙的博客

UWP WPF 解决 xaml 设计显示异常

例如我创建一个用户控件 TsjcyubtnTtqtjem 那么就可以在构造函数添加下面代码

22820
来自专栏技术之路

【权限的思考】(一)使用反射实现动态权限

  每一个业务系统都会根据业务需要配置各种各样的权限,实现方式也是千差万别,各有各的优缺点。今天我们 利用反射来做一个小的权限管理Demo。也可以说是插件化的权...

23090
来自专栏木宛城主

SharePoint中在线编辑文档

我一直以为只有在Document Library里面的File才会支持在线编辑。直到今天早上我才发现用IE打开List里面的Attachments也是支持在线...

40160
来自专栏dotnet & java

WCF 入门 (17)

首先修改服务端的app.config 配置文件,先使用basicHttpBinding

9120
来自专栏技术小讲堂

探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式

如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网...

28980
来自专栏Java大联盟

Java爬虫入门

83440
来自专栏木宛城主

SharePoint下利用DocX组件导出Word

平常开发时,或多或少都需要和Word打交道,特变是编辑、导出Word。 利用DocX,开源的读写Word组件,可以快速帮助我们进行对Word的操作。 Do...

26850

扫码关注云+社区

领取腾讯云代金券