我的个人博客:http://www.lovecoding.com.cn

自己动手用Javascript写一个无刷新分页控件

.NET技术交流群:337901356 ,欢迎您的加入!

对 于一个用户体验好的网站来说,无刷新技术是很重要的,无刷新,顾名思义,就是局部刷新数据,有用过Asp.net Web Form技术开发网页的人,可能对服务器端(具有runat="server"属性)的控件的回发(PostBack)特性有一定的了解。我们知道,只要 一点击页面中的Asp.net按钮(可能是LinkButton,也可能是Button,还有可能是ImageButton等)都会引起整个页面的刷新, 这样的体验是非常不好的,因为点击按钮后导致的操作是重新给服务器发送一个请求,重新执行一次页面的服务端代码,重新生成html,然后响应生成的页面内 容,发回浏览器端。这样无形中增大了网络浏览,用户等待页面的响应时间增长等。 有时我们点击某个按钮目的只是为了某个区域的数据被更新,而其他的区域的数据不变,这个时候我们就可以使用Ajax技术(Asynchronous Javascript And XML)称为异步Javascript 和 XML. 但是往往我们站点中的数据不止一条,但又要有页面无刷新(其实是局部刷新)的效果,那么分页的时候我们就不能在网上去下载服务端的分页控件(如 AspNetPager)来进行分页,因为服务器端的分页控件会和后台相关联,只能通过Javascript代码来编写一个分页控件来进行分页。 废话不多话说,看分页代码。 为了证明是无刷新分页,这里我们page.html这个静态页面来呈现从数据库中取到的数据。 page.html页面代码如下 

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <link href="../分页控件/Page.css" rel="stylesheet" />
    <script src="../分页控件/Page.js"></script>
    <style type="text/css">
        .b {
            color: red;
            text-align: center;
            margin-top: 100px;
        }
        th {
            padding: 10px;
        }
        .td {
            border-left: 1px solid #E0E0E0;
            border-top: 1px solid #E0E0E0;
            padding: 10px;
            color: Brown;
            text-align: center;
        }
        .table {
            border-bottom: 1px solid #E0E0E0;
            border-right: 1px solid #E0E0E0;
            width: 80%;
        }
    </style>
</head>
<body>
    <div style="width:800px;margin:0px auto;border:1px solid Gray;height:1000px;">
        <!--用于呈现要显示的数据的div-->
        <div id="content" style="height:auto;">
            <!--<select id="sel"></select>-->
        </div>
        <!--用于呈现分页控件的Div-->
        <div id="pager">
        </div>

<script type="text/javascript">
            var totalRecord = 0;
            var xmlHttpRequest = new XMLHttpRequest();
            xmlHttpRequest.open("get", "../ashx文件/GetRecordCount.ashx", true);
            xmlHttpRequest.onreadystatechange = function () {
                if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == "200") {
                    totalRecord = parseInt(xmlHttpRequest.responseText, 10);
                    InitializePageControl(10, totalRecord, function () {
                        var xmlHttp = new XMLHttpRequest();
                        xmlHttp.open("get", "../aspx页面/GetProduct.aspx?pageIndex=" + (this.pageIndex) + "&pageSize=" + (this.pageSize), true);
                        xmlHttp.onreadystatechange = function () {
                            if (xmlHttp.readyState == 4 && xmlHttp.status == "200") {
                                var content = document.getElementById("content");
                                content.innerHTML = "";
                                content.innerHTML = xmlHttp.responseText;
                            }
                        }
                        xmlHttp.send(null);
                    }, document.getElementById("pager"));
                }
            }
            xmlHttpRequest.send(null);
</script>
</div>
</body>
</html>
返回数据的页面:GetProduct.aspx页面
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
:
 
 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GetProduct.aspx.cs" Inherits="开源代码.aspx页面.GetProduct" %>
<asp:repeater id="Repeater1" runat="server">
<HeaderTemplate>
    <table class="table">
        <tr>
            <th>编号</th>
            <th>姓名</th>
            <th>产品编号</th>
            <th>颜色</th>
        </tr>
</HeaderTemplate>
<ItemTemplate>
    <tr>
        <td class="td"><%#Eval("ProductID") %></td>
        <td class="td"><%#Eval("Name") %></td>
        <td class="td"><%#Eval("ProductNumber") %></td>
        <td class="td"><%#Eval("Color") %></td>
    </tr>
</ItemTemplate>
<FooterTemplate>
    </table>
</FooterTemplate>
</asp:repeater>
GetProduct.aspx.cs:
 
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace 开源代码.aspx页面
{
    public partial class GetProduct : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                Bind();
            }
        }
        private void Bind()
        {
            string pageIndex = Request.QueryString["pageIndex"];
            int pageSize = int.Parse(Request.QueryString["pageSize"]);
            if (!string.IsNullOrEmpty(pageIndex))
            {
                int p = int.Parse(pageIndex);
                using (SqlConnection conn = new SqlConnection("Data Source=chenxin-pc;Initial Catalog=AdventureWorks;Integrated Security=True"))
                {
                    using (SqlCommand comm = conn.CreateCommand())
                    {
                        try
                        {
                            comm.CommandText = "with tmp as (select Row_Number() over(order by ProductID) RowIndex,* from Production.Product) select * from tmp where RowIndex between " + ((p - 1) * pageSize) + " and " + (p * pageSize);
                            SqlDataAdapter adapter = new SqlDataAdapter(comm);
                            DataTable dt = new DataTable();
                            adapter.Fill(dt);
                            this.Repeater1.DataSource = dt;
                            this.Repeater1.DataBind();
                        }
                        catch (Exception ex)
                        {
                            Response.Write("服务器内部异常!");
                        }
                    }
                }
            }
            else
            {
                Response.Write("请求的页错误!");
            }
        }
    }
}
最后:Page.js代码如下
//用于初始化页面,调用该方法,使得第一次进入页面时加载第一页数据,并且初始化分页控件。
//pageSize:每页要显示几条记录。
//totalRecord:总共有多少条记录。
//clickFunction:点击分页按钮时要执行的函数。
//containers:一个Dom对象,表示要将分页控件呈现在哪一个元素中。
function InitializePageControl(pageSize, totalRecord, clickFunction, container) {
    this.pageIndex = 1;
    this.pageSize = pageSize;
    clickFunction.call(this);
    PageControl(1, pageSize, totalRecord, clickFunction, container);
}
//根据参数来创建一个超链接
function createAnchor(params) {
    var a = document.createElement("a");
    for (var attr in params) {
        a[attr] = params[attr];
    }
    return a;
}
//pageIndex:当前要显示的是第几页。
//pageSize:每页要显示几条记录。
//totalRecord:总共有多少条记录。
//clickFunction:点击分页按钮时要执行的函数。
//containers:一个Dom对象,表示要将分页控件呈现在哪一个元素中。
function PageControl(pageIndex, pageSize, totalRecord, clickFunction, container) {
    container.innerHTML = "";
    if (totalRecord <= 0) {
        return false;
    }
    var divContainer = document.createElement("div");
    divContainer.className = "divContainer";
    //函数func用于用户点击每一个分页按钮时,PageControl内部要处理的函数。
    var func = function () {
        //当前这个this是指被点击的分页按钮中的某个超链接对象。
        this.pageSize = pageSize;
        clickFunction.call(this);
        PageControl(this.pageIndex, pageSize, totalRecord, clickFunction, container);
    };
    //求出总共多少页
    var pageCount = Math.ceil(totalRecord / pageSize);
    //上一页的超链接 只有总页数大于2页,并且当前显示的页不是第一页的时候才显示上一页
    if (pageCount > 2 && pageIndex != 1) {
        var previousPage = createAnchor(
            {
                "id": "previousPage",
                "href": "#",
                "className": "a",
                "innerHTML": "上一页",
                "onclick": func,
                "pageIndex": pageIndex - 1
            }
        );
        divContainer.appendChild(previousPage);
    }
    var params =
              {
                  "href": "#",
                  "className": "a",
                  "onclick": func
              }
    //如果总页数大于8页,则要出现...的形式。
    if (pageCount > 8) {
        var firstPage = createAnchor({ "href": "#", "className": "a", "innerHTML": 1, "pageIndex": 1, "onclick": func });
        var lastPage = createAnchor({ "href": "#", "className": "a", "innerHTML": pageCount, "pageIndex": pageCount, "onclick": func });
        if (pageIndex > 4 && pageIndex + 4 <= pageCount) {
            divContainer.appendChild(firstPage);
            var a = createAnchor({ "innerHTML": "..." });
            divContainer.appendChild(a);
            for (var i = pageIndex - 2; i <= pageIndex + 2; i++) {
                params.className = "a";
                params.innerHTML = i.toString();
                params.pageIndex = i;
                if (i == pageIndex) {
                    params.className += " current";
                }
                a = createAnchor(params);
                divContainer.appendChild(a);
            }
            a = createAnchor({ "innerHTML": "..." });
            divContainer.appendChild(a);
            divContainer.appendChild(lastPage);
        }//当前要显示的页数<=4页
        else if (pageIndex <= 4) {
            for (var i = 1; i <= 6; i++) {
                params.className = "a";
                params.innerHTML = i.toString();
                params.pageIndex = i;
                if (i == pageIndex) {
                    params.className += " current";
                }
                a = createAnchor(params);
                divContainer.appendChild(a);
            }
            a = createAnchor({ "innerHTML": "..." });
            divContainer.appendChild(a);
            divContainer.appendChild(lastPage);
        }//当前要显示的是最后一页。
        else {
            divContainer.appendChild(firstPage);
            a = createAnchor({ "innerHTML": "...", "className": "a" });
            divContainer.appendChild(a);
            for (var i = pageCount - 5; i <= pageCount; i++) {
                params.className = "a";
                params.innerHTML = i.toString();
                params.pageIndex = i;
                if (i == pageIndex) {
                    params.className += " current";//不要漏了current前面的空格哦
                }
                a = createAnchor(params);
                divContainer.appendChild(a);
            }
        }
    }//总页数<=8页,那么就直接显示所有的页数
    else {
        for (var i = 1; i <= pageCount; i++) {
            params.className = "a";
            params.innerHTML = i.toString();
            params.pageIndex = i;
            if (i == pageIndex) {
                params.className += " current";
            }
            a = createAnchor(params);
            divContainer.appendChild(a);
        }
    }
    //之用总页数大于2页,并且当前显示的页<总页数的时候才显示下一页
    if (pageCount >= 2 && pageIndex < pageCount) {
        var nextPage = createAnchor(
               {
                   "id": "nextPage",
                   "href": "#",
                   "className": "a",
                   "innerHTML": "下一页",
                   "onclick": func,
                   "pageIndex": (pageIndex + 1)
               }
               );
        divContainer.appendChild(nextPage);
    }
    var span = document.createElement("span");
    span.textContent = "转到";
    span.className = "span";
    divContainer.appendChild(span);
    var input = document.createElement("input");
    input.type = "text";
    input.value = pageIndex.toString();
    input.id = "txtPageIndex";
    input.className = "input";
    divContainer.appendChild(input);
    span = document.createElement("span");
    span.innerHTML = "页";
    span.className = "span";
    divContainer.appendChild(span);
    var go = document.createElement("input");
    go.type = "button";
    go.className = "go";
    go.value = "Go";
    go.onclick = function () {
        var txtPageIndex = document.getElementById("txtPageIndex");
        try {
            //alert("value" in txtPageIndex);
            var pageIndex = parseInt(txtPageIndex.value, 10);
            if (pageIndex < 1 || pageIndex > pageCount) {
                alert("页数的合法范围: 1-" + pageCount);
            }
            else if (isNaN(pageIndex)) {
                alert("页数必须为数字!");
            }
            else {
                //这里面的this是指input,但是因为input这个东西并没有pageIndex属性,所以我们必须给其添加进去
                this.pageIndex = pageIndex;
                this.pageSize = pageSize;
                clickFunction.call(this);
                PageControl(pageIndex, pageSize, totalRecord, clickFunction, container);
            }
        }
        catch (error) {
            alert("描述:" + error.description + " 详细信息: " + error.stack + error.message);
        }
    }
    divContainer.appendChild(go);
    container.appendChild(divContainer);
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 
 
 

 

posted @ 2014-02-17 15:39  chenxin.dm  阅读(1236)  评论(1编辑  收藏  举报
我的个人博客:http://www.lovecoding.com.cn