Ajax分页研究+实例

最近在尝试更新blog代码的时候遇到一个问题
如何利用ajax实现无刷新分页了?
我们知道利用DataList和DataGrid在服务端分页时很简单的
但是大家都知道其是将数据一次性读取出来至于DataSet中
数据量很大时极为浪费服务器内存  效率很低
所以大数据量时并不推荐使用.NET自带的分页功能
通常来说 对于Sql等数据库 我们采用分页存储过程+分页控件来实现高效率的分页
这里存储过程我一般是采用邹健的那个 而分页控件一般采用吴旗娃的ASPNetPager

以上的分页方式对于ajax来说一样的
大致思路有两种

1.在客户端传递页码到服务端 服务端根据页码在数据库中取出相应的数据记录
生成datase或通过我前面一片日志里面推荐的使用LoadTemplate方法生成string返回给客户端
然后客户端更新html即可,这里需要分页的sql语句,对于access 我参考了博客园李洪根推荐的select top语句
详细见他的blog

2.对于小数据量的分页 如果你sql不熟 也可以将数据一次性读取到dataset
根据页码 计算当前页的记录编号 生成子dataset 返回同上的结果即可
这样做只涉及到简单的数学计算 利用datatable的rows.count很容易实现
附:datatable的复制
etc:
        DataTable dt2=dt.Clone();
        for(int i=0;i<dt.Rows.Count;i++)
        {
            dt2.ImportRow(dt.Rows[i]);
        }

第二种方法稍微简单 只讨论第一种方法
需要注意的是 我们在客户端传递页码
那么我们必须在客户端生成相应的分页代码
js代码参考
    
            strHtml += '<span class="count">Pages: ' + this.page + ' / ' + this.pageCount + '</span>';
            strHtml += '<span class="number">';
            if (prevPage < 1) {
                strHtml += '<span title="First Page">&#171;</span>';
                strHtml += '<span title="Prev Page">&#139;</span>';
            } else {
                strHtml += '<span title="First Page"><a href="javascript:loadpage(1)">&#171;</a></span>';
                strHtml += '<span title="Prev Page"><a href="javascript:loadpage('+prevPage+')">&#139;</a></span>';
            }
            if (this.page % 10 ==0) {
                var startPage = this.page - 9;
            } else {
                var startPage = this.page - this.page % 10 + 1;
            }
            if (startPage > 10) strHtml += '<span title="Prev 10 Pages"><a href="javascript:loadpage('+ (startPage - 1) +')">...</a></span>';
            for (var i = startPage; i < startPage + 10; i++) {
                if (i > this.pageCount) break;
                if (i == this.page) {
                    strHtml += '<span title="Page ' + i + '">[' + i + ']</span>';
                } else {
                    strHtml += '<span title="Page ' + i + '"><a href="javascript:loadpage('+i+')">[' + i + ']</a></span>';
                }
            }
            if (this.pageCount >= startPage + 10) strHtml += '<span title="Next 10 Pages"><a href="javascript:loadpage('+(startPage + 10)+')">...</a></span>';
            if (nextPage > this.pageCount) {
                strHtml += '<span title="Next Page">&#155;</span>';
                strHtml += '<span title="Last Page">&#187;</span>';
            } else {
                strHtml += '<span title="Next Page"><a href="javascript:loadpage('+nextPage+')">&#155;</a></span>';
                strHtml += '<span title="Last Page"><a href="javascript:loadpage('+this.pageCount+')">&#187;</a></span>';
            }
            strHtml += '</span><br />';
            break;

上面的代码是生成分页的核心代码 这样 通过自定义的loadpage(obj)事件[obj就是点击的页码]
我们可以利用ajax向服务端传递当前页码以获取返回结果
服务端首先需要的是一个Access的分页类 我自己写了一个
public class AccessPager
    {
        //internal member
        private string table=string.Empty;
        private int pagesize=10;
        private int pageindex=1;
        private string orderkey = string.Empty;
        /// <summary>
        /// contrustors
        /// </summary>
        /// <param name="tablename"></param>
        /// <param name="curpage"></param>
        /// <param name="size"></param>
        public AccessPager(string tablename, int curpage, int size,string key)
        {
            table = tablename;
            pagesize = size;
            pageindex = curpage;
            orderkey = key;
        }
        /// <summary>
        /// get record count
        /// </summary>
        /// <returns></returns>
        public int recCount()
        {
            string sql = "select count(*) from " + table;
            return (int)AccessHelper.ExecuteScalar(System.Data.CommandType.Text, sql, null);
        }
        /// <summary>
        /// get all page count
        /// </summary>
        /// <returns></returns>
        public int pageCount()
        {
            if (recCount() % pagesize == 0)
                return recCount() / pagesize;
            else
                return (recCount() / pagesize) + 1;
        }
        /// <summary>
        /// get dataset
        /// </summary>
        /// <returns></returns>
        public System.Data.DataSet ExecuteDataSet()
        {
            string sql = string.Empty;
            if (pageCount() > 1)
            {
                if (pageindex == 1)
                    sql = "select top " + pagesize.ToString() + " * from " + table + " order by " + orderkey + " desc";
                else if (pageindex < pageCount())
                {
                    int endcount = pagesize * (pageindex-1);
                    sql = "select top " + pagesize.ToString() + " * from " + table + " where (" + orderkey + "<(select min(" + orderkey + ") from (select top "+endcount.ToString()+" "+orderkey+" from "+table+" order by "+orderkey+" desc) as t)) order by "+orderkey+" desc";                     
                }
                else if(pageindex>=pageCount())
                {
                    if (recCount() % pagesize == 0)
                    {
                        sql = "select top " + pagesize.ToString() + " * from " + table + " order by " + orderkey + " desc";
                    }
                    else
                    {
                        int pLeft=recCount()%pagesize;
                        int endcount = pagesize * (pageindex - 1);
                        sql = "select top " +pLeft+ " * from " + table + " where (" + orderkey + "<(select min(" + orderkey + ") from (select top " + endcount.ToString() + " " + orderkey + " from " + table + " order by " + orderkey + " desc) as t)) order by " + orderkey + " desc";                     
                    }
                }
            }
            else
                sql = "select * from " + table+" order by "+orderkey+" desc";
            return AccessHelper.ExecuteDataset(sql, System.Data.CommandType.Text, null);
        }
    }

这样就可以根据表名称 排序id(我这个类只针对有编号且编号为主键的情况)页码 每页大小取出dataset了

然后 在页面的ajax方法中 我们 首先 默认情况下载入第一页的数据
      <div id="main">
        <script language="javascript" type="text/javascript">
           Blog_index.getData(1,2,_callback);
           function _callback(res){
            $('main').innerHTML=res.value; } 
        </script>      
      </div>    
当点击js生成的分页控件上的页码时  触发以下事件
    <script language="javascript" type="text/javascript">                        
        function loadpage(obj){
        $('main').innerHTML='<img src="../images/indicator.gif" alt="" />数据载入中......'
        $('txtPageCount').value=obj;
        var pg2 = new showPages('pg');
        pg2.pageCount =<%=getCount(2)%>; 
        pg2.page= $('txtPageCount').value;
        pg2.printHtml(1); 
        Blog_index.getData(obj,2,loadpage_callback);
        } 
      function loadpage_callback(res){        
      $('main').innerHTML=res.value; 
      }     
    </script>   

下面的是js生成分页控件的代码
    
    <div id="page_container">
     <div id="Pages"></div>
      <input id="txtPageCount" type="text"  style="display:none"/>
      <script language="javascript" type="text/javascript">
                var pg = new showPages('pg');
                pg.pageCount =<%=getCount(2)%>;
                pg.page=1;
                pg.printHtml(1); 
       </script
    </div>
 可以看到 我使用了一个隐藏的input来存储当前页码 这个是必要的
 也可以改写为改变url生成?page=88类似的 但是那样会引起页面刷新 我们的ajax分页也就算失去意义了

 通过以上的步骤 ajax分页就完成了
查看实例地址:

http://www.suanshu.net/blog/pager.aspx
posted @ 2007-01-07 10:23  海浪~~  阅读(3625)  评论(1)    收藏  举报