关注电子商务网站开发-《JS+AJAX写符合SEO规范的无刷新分页》

无刷新分页相信大家也看过不少,包括一些Jquery的分页插件。之前做产品分页的时候也下载研究过几个,但是用现在的话说就是硬伤很多,不说代码太多以及和自己数据库很难对接,从SEO的角度考虑(必须要有有质量的链接),实在是就没办法用了。于是就决定自己写了一个,一方面本人确实也称不上高手,还是那句话,贴出来供大家参考,另一方面,文采很差,所以尽量少说话,多解释代码。

说明

无刷新的分页主要分为三个步骤

步骤 A:数据库分页查询

    方法A1

       方法A2

步骤B:后台分页处理

     步骤B1

       步骤B2

步骤C:前台分页调用。

          步骤C1

          步骤C2

惯例结尾会把实例附上。

 

 

步骤A :数据库分页查询

这里提供两种方法

方法A1:SQL SERVER自带的分页查询语法

用我们这边的产品数据库做实例:查询产品表Product中产品名(ProductName)中带S的的第一页数据,限制每页个数为10,代码:

 

declare @pageIndex int--页数索引
declare @keyWord varchar(50)--搜索关键词
declare @pageCount int--每页数据个数
set @pageIndex=1
set @keyWord='S'
set @pageCount=10;
with Row as(SELECT row_number() over( order by addtime) as Num,AddTime,ProductName from Product where ProductName like '%'+@keyWord+'%' ) select top 10 * from Row where Num>(@pageIndex-1) * @pageCount  and  Num<= @pageIndex* @pageCount

 

结果返回一个DatatTable。这是一种比较简单的方法,代码也比较少,当然,支持的功能也有限,如果只是想简单的实现分页功能,可以考虑一下。

方法A2:SQL SERVER分页存储过程

此存储过程是我在网上搜到的,具体地址我也记不清了,刚才在百度上搜了一下竟然没搜到,在这里只能向作者说声抱歉,贴一下你的代码,如果有人能找到作者的原贴请留言发下地址,我会及时贴上去的。

View Code
CREATE PROC [dbo].[P_viewPage]

 

    @TableName VARCHAR(200),     --表名
    @FieldList VARCHAR(2000),    --显示列名,如果是全部字段则为*
    @PrimaryKey VARCHAR(100),    --单一主键或唯一值键
    @Where VARCHAR(2000),        --查询条件不含'where'字符,如id>10 and len(userid)>9
    @Order VARCHAR(1000),        --排序不含'order by'字符,如id asc,userid desc,必须指定asc或desc                                 
                                 --注意当@SortType=3时生效,记住一定要在最后加上主键,否则会让你比较郁闷
    @SortType INT,               --排序规则1:正序asc 2:倒序desc 3:多列排序方法
    @RecorderCount INT,          --记录总数0:会返回总记录
    @PageSize INT,               --每页输出的记录数
    @PageIndex INT,              --当前页数
    @TotalCount INT OUTPUT,      --记返回总记录
    @TotalPageCount INT OUTPUT   --返回总页数
AS
    SET NOCOUNT ON

    IF ISNULL(@TotalCount,'') = '' SET @TotalCount = 0
    SET @Order = RTRIM(LTRIM(@Order))
    SET @PrimaryKey = RTRIM(LTRIM(@PrimaryKey))
    SET @FieldList = REPLACE(RTRIM(LTRIM(@FieldList)),' ','')

    WHILE CHARINDEX(', ',@Order) > 0 OR CHARINDEX(' ,',@Order) > 0
    BEGIN
        SET @Order = REPLACE(@Order,', ',',')
        SET @Order = REPLACE(@Order,' ,',',')    
    END

    IF ISNULL(@TableName,'') = '' OR ISNULL(@FieldList,'') = '' 
        OR ISNULL(@PrimaryKey,'') = ''
        OR @SortType < 1 OR @SortType >3
        OR @RecorderCount  < 0 OR @PageSize < 0 OR @PageIndex < 0        
    BEGIN 
        PRINT('ERR_00')       
        RETURN
    END    

    IF @SortType = 3
    BEGIN
        IF (UPPER(RIGHT(@Order,4))!=' ASC' AND UPPER(RIGHT(@Order,5))!=' DESC')
        BEGIN PRINT('ERR_02') RETURN END
    END

    DECLARE @new_where1 VARCHAR(1000)
    DECLARE @new_where2 VARCHAR(1000)
    DECLARE @new_order1 VARCHAR(1000)   
    DECLARE @new_order2 VARCHAR(1000)
    DECLARE @new_order3 VARCHAR(1000)
    DECLARE @Sql VARCHAR(8000)
    DECLARE @SqlCount NVARCHAR(4000)

    IF ISNULL(@where,'') = ''
        BEGIN
            SET @new_where1 = ' '
            SET @new_where2 = ' WHERE  '
        END
    ELSE
        BEGIN
            SET @new_where1 = ' WHERE ' + @where 
            SET @new_where2 = ' WHERE ' + @where + ' AND '
        END

    IF ISNULL(@order,'') = '' OR @SortType = 1  OR @SortType = 2 
        BEGIN
            IF @SortType = 1 
            BEGIN 
                SET @new_order1 = ' ORDER BY ' + @PrimaryKey + ' ASC'
                SET @new_order2 = ' ORDER BY ' + @PrimaryKey + ' DESC'
            END
            IF @SortType = 2 
            BEGIN 
                SET @new_order1 = ' ORDER BY ' + @PrimaryKey + ' DESC'
                SET @new_order2 = ' ORDER BY ' + @PrimaryKey + ' ASC'
            END
        END
    ELSE
        BEGIN
            SET @new_order1 = ' ORDER BY ' + @Order
        END

    IF @SortType = 3 AND  CHARINDEX(','+@PrimaryKey+' ',','+@Order)>0
        BEGIN
            SET @new_order1 = ' ORDER BY ' + @Order
            SET @new_order2 = @Order + ','            
            SET @new_order2 = REPLACE(REPLACE(@new_order2,'ASC,','{ASC},'),'DESC,','{DESC},')            
            SET @new_order2 = REPLACE(REPLACE(@new_order2,'{ASC},','DESC,'),'{DESC},','ASC,')
            SET @new_order2 = ' ORDER BY ' + SUBSTRING(@new_order2,1,LEN(@new_order2)-1)            
            IF @FieldList <> '*'
                BEGIN            
                    SET @new_order3 = REPLACE(REPLACE(@Order + ',','ASC,',','),'DESC,',',')                              
                    SET @FieldList = ',' + @FieldList                    
                    WHILE CHARINDEX(',',@new_order3)>0
                    BEGIN
                        IF CHARINDEX(SUBSTRING(','+@new_order3,1,CHARINDEX(',',@new_order3)),','+@FieldList+',')>0
                        BEGIN 
                        SET @FieldList = 
                            @FieldList + ',' + SUBSTRING(@new_order3,1,CHARINDEX(',',@new_order3))                        
                        END
                        SET @new_order3 = 
                        SUBSTRING(@new_order3,CHARINDEX(',',@new_order3)+1,LEN(@new_order3))
                    END
                    SET @FieldList = SUBSTRING(@FieldList,2,LEN(@FieldList))                     
                END            
        END

    SET @SqlCount = 'SELECT @TotalCount=COUNT(*),@TotalPageCount=CEILING((COUNT(*)+0.0)/'
                    + CAST(@PageSize AS VARCHAR)+') FROM ' + @TableName + @new_where1
    
    IF @RecorderCount  = 0
        BEGIN
             EXEC SP_EXECUTESQL @SqlCount,N'@TotalCount INT OUTPUT,@TotalPageCount INT OUTPUT',
                               @TotalCount OUTPUT,@TotalPageCount OUTPUT
        END
    ELSE
        BEGIN
             SELECT @TotalCount = @RecorderCount            
        END

    IF @PageIndex > CEILING((@TotalCount+0.0)/@PageSize)
        BEGIN
            SET @PageIndex =  CEILING((@TotalCount+0.0)/@PageSize)
        END

    IF @PageIndex = 1 OR @PageIndex >= CEILING((@TotalCount+0.0)/@PageSize)
        BEGIN
            IF @PageIndex = 1 --返回第一页数据
                BEGIN
                    SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ' 
                               + @TableName + @new_where1 + @new_order1
                END
            IF @PageIndex >= CEILING((@TotalCount+0.0)/@PageSize)  --返回最后一页数据
                BEGIN
                    SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM (' 
                               + 'SELECT TOP ' + STR(ABS(@PageSize*@PageIndex-@TotalCount-@PageSize)) 
                               + ' ' + @FieldList + ' FROM '
                               + @TableName + @new_where1 + @new_order2 + ' ) AS TMP '
                               + @new_order1                    
                END        
        END    
    ELSE
        BEGIN
            IF @SortType = 1  --仅主键正序排序
                BEGIN
                    IF @PageIndex <= CEILING((@TotalCount+0.0)/@PageSize)/2  --正向检索
                        BEGIN
                            SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ' 
                                       + @TableName + @new_where2 + @PrimaryKey + ' > '
                                       + '(SELECT MAX(' + @PrimaryKey + ') FROM (SELECT TOP '
                                       + STR(@PageSize*(@PageIndex-1)) + ' ' + @PrimaryKey 
                                       + ' FROM ' + @TableName
                                       + @new_where1 + @new_order1 +' ) AS TMP) '+ @new_order1
                        END
                    ELSE  --反向检索
                        BEGIN
                            SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM (' 
                                       + 'SELECT TOP ' + STR(@PageSize) + ' ' 
                                       + @FieldList + ' FROM '
                                       + @TableName + @new_where2 + @PrimaryKey + ' < '
                                       + '(SELECT MIN(' + @PrimaryKey + ') FROM (SELECT TOP '
                                       + STR(@TotalCount-@PageSize*@PageIndex) + ' ' + @PrimaryKey 
                                       + ' FROM ' + @TableName
                                       + @new_where1 + @new_order2 +' ) AS TMP) '+ @new_order2 
                                       + ' ) AS TMP ' + @new_order1
                        END
                END
            IF @SortType = 2  --仅主键反序排序
                BEGIN
                    IF @PageIndex <= CEILING((@TotalCount+0.0)/@PageSize)/2  --正向检索
                        BEGIN
                            SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ' 
                                       + @TableName + @new_where2 + @PrimaryKey + ' < '
                                       + '(SELECT MIN(' + @PrimaryKey + ') FROM (SELECT TOP '
                                       + STR(@PageSize*(@PageIndex-1)) + ' ' + @PrimaryKey 
                                       +' FROM '+ @TableName
                                       + @new_where1 + @new_order1 + ') AS TMP) '+ @new_order1                               
                        END 
                    ELSE  --反向检索
                        BEGIN
                            SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM (' 
                                       + 'SELECT TOP ' + STR(@PageSize) + ' ' 
                                       + @FieldList + ' FROM '
                                       + @TableName + @new_where2 + @PrimaryKey + ' > '
                                       + '(SELECT MAX(' + @PrimaryKey + ') FROM (SELECT TOP '
                                       + STR(@TotalCount-@PageSize*@PageIndex) + ' ' + @PrimaryKey 
                                       + ' FROM ' + @TableName
                                       + @new_where1 + @new_order2 +' ) AS TMP) '+ @new_order2 
                                       + ' ) AS TMP ' + @new_order1
                        END  
                END                         
            IF @SortType = 3  --多列排序,必须包含主键,且放置最后,否则不处理
                BEGIN
                    IF CHARINDEX(',' + @PrimaryKey + ' ',',' + @Order) = 0 
                    BEGIN PRINT('ERR_02') RETURN END
                    IF @PageIndex <= CEILING((@TotalCount+0.0)/@PageSize)/2  --正向检索
                        BEGIN
                            SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ( '
                                       + 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ( '
                                       + ' SELECT TOP ' + STR(@PageSize*@PageIndex) + ' ' + @FieldList
                                       + ' FROM ' + @TableName + @new_where1 + @new_order1 + ' ) AS TMP '
                                       + @new_order2 + ' ) AS TMP ' + @new_order1    
                        END
                    ELSE  --反向检索
                        BEGIN
                            SET @Sql = 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ( '  
                                       + 'SELECT TOP ' + STR(@PageSize) + ' ' + @FieldList + ' FROM ( '
                                       + ' SELECT TOP ' + STR(@TotalCount-@PageSize*@PageIndex+@PageSize) + ' ' + @FieldList
                                       + ' FROM ' + @TableName + @new_where1 + @new_order2 + ' ) AS TMP '
                                       + @new_order1 + ' ) AS TMP ' + @new_order1
                        END
                END
        END
    PRINT(@Sql)
EXEC(@Sql)

各个参数作者都做了解释,只要给各个参数赋值,执行存储过程就可以得到一个相应的Datatable。

 

 

步骤B:后台分页处理

分页处理方法也就是前台ajax调用的方法,有两个参数,参数PageIndex  int类型,为当前页数;参数key,搜索产品关键词。方法返回List<String>类型,方法声明代码(.NET):

  [WebMethod]
    public static List<String> LoadProduct(int PageIndex, String key)
    {
    List<String> list = new List<String>();

    //..
    return list;
  }

 

实例中用的数据库查询方法是A2方法SQL SERVER分页存储过程,本人亲测百万条数据情况下执行这个存储过程没什么压力。在分页处理方法中声明参数的代码:

     string TableName = "VProducts";//表名
        string FieldList = "Pictures,ProductName,IDPlus,addtime";//字段集合
        string PrimaryKey = "IDPlus";//主键
        string Order = "IDPlus desc";//排序
        int SortType = 2;//排序规则 1:正序asc 2:倒序desc 3:多列排序方法
        int RecorderCount = 0;//字段集合
        int PageSize = 4;//每页输出的记录数
        String where = "ProductName like '%" + key + "%'";
        SqlParameter[] paras = 
            {
                new SqlParameter("@TableName",TableName),
                new SqlParameter("@FieldList",FieldList),
                new SqlParameter("@TotalPageCount",SqlDbType.Int),
                new SqlParameter("@TotalCount",SqlDbType.Int),
                new SqlParameter("@PrimaryKey",PrimaryKey),
                new SqlParameter("@Where",where),
                new SqlParameter("@Order",Order),
                new SqlParameter("@SortType",SortType),
                new SqlParameter("@RecorderCount",RecorderCount),
                new SqlParameter("@PageSize",PageSize),
                new SqlParameter("@PageIndex",PageIndex)
            };
        paras[2].Direction = ParameterDirection.InputOutput;//设置
        paras[2].Value = 0;
        paras[3].Direction = ParameterDirection.InputOutput;//设置
        paras[3].Value = 0;
     DataTable  DT = DBHelper.GetDataTable("P_viewPage", paras);//执行存储过程得到Datatable 

通过执行存储过程得到一个DataTable。之后要进行两个步骤操作。

步骤B1 遍历这个datatable,然后填充到一个HTML模板里。

这个HTML模板就是显示单条产品的HTML元素,如实例中把每个产品显示在一个li里

String Temp = @"<li class='last'>
                            <div class='pic'>
                                <a href='javascript:void(0)'>
                                    <img width='160' src='{0}'  /></a>
                            </div>
                            <div class='name'>
                                <a href='javascript:void(0)'>{1}</a>
                            </div>
                        </li>";

然后就可以填充了,代码:

     StringBuilder SB = new StringBuilder();//建议用StringBuilder

        int PageNum = Convert.ToInt32(paras[2].Value);//输出参数 总页数
        int ProductCount = Convert.ToInt32(paras[3].Value);//输出参数 总个数
        if (DT != null && DT.Rows.Count != 0)
        {
            for (int i = 0; i < DT.Rows.Count; i++)
            {
             
                SB.AppendFormat(Temp, DT.Rows[i]["Pictures"].ToString(), DT.Rows[i]["ProductName"].ToString());
            }
        }


存储过程还有两个输出参数,分别记录总页数和总个数。

步骤B2

 

步骤B1已经得到了该页数的所有数据,步骤B2是关于页数的操作,如图:

这一块的代码要根据当前页数及总页数生产,并且为每页分配一个可用连接,当在浏览器中输入该连接,会加载该页的产品。代码:

View Code
StringBuilder SBPage = new StringBuilder();
        if (PageNum != 0)
        {
            #region 分页显示
            string path = System.Web.HttpContext.Current.Request.UrlReferrer + (key != "" ? "&" : "?") + "pageindex=";//判断是否有参数key
            string strFirstTemp = "<li><a   onclick='return getList(1);'  href='" + path + "1'>首页</a></li>";//拼接url
            string strLastTemp = "<li><a  onclick='return getList(" + (PageNum).ToString() + ");' href='" + path + (PageNum).ToString() + "' >尾页</a></li>";
            string strFrontTemp = "<li><a onclick='return getList(" + (PageIndex - 1).ToString() + ");'  href='" + path + (PageIndex - 1).ToString() + "' >上一页</a></li>";
            string strNextTemp = "<li><a onclick='return getList(" + (PageIndex + 1).ToString() + ");'  href='" + path + (PageIndex + 1).ToString() + "' >下一页</a></li>";
            string strCurrentTemp = "<li><span >{0}</span></li>";
            string strPageTemp = "<li><a  onclick='return getList({0});' href='" + path + "{0}'>{0}</a></li>";
            //若页数=1
            if (PageNum == 1)
            {
                SBPage.AppendFormat(strCurrentTemp, 1);
            }
            else//若页数大于1
            {
                if (PageIndex == 1)//若当前页=1
                {
                    SBPage.AppendFormat(strCurrentTemp, 1);
                    if (PageNum <= 10)//若总页数小于等于10
                    {
                        for (int i = 2; i <= PageNum; i++)
                        {
                            SBPage.AppendFormat(strPageTemp, i);
                        }
                    }
                    else//若总页数大于10
                    {
                        for (int i = 2; i <= 10; i++)
                        {
                            SBPage.AppendFormat(strPageTemp, i);
                        }
                    }
                    SBPage.Append(strNextTemp);
                    SBPage.Append(strLastTemp);
                }
                else if (PageIndex == PageNum)//若当前页等于总页数
                {
                    SBPage.Append(strFirstTemp);
                    SBPage.Append(strFrontTemp);
                    if (PageNum <= 10)//若总页数小于等于10
                    {
                        for (int i = 1; i < PageNum; i++)
                        {
                            SBPage.AppendFormat(strPageTemp, i);
                        }
                    }
                    else//若总页数大于10
                    {
                        for (int i = (PageNum - 9); i < PageNum; i++)
                        {
                            SBPage.AppendFormat(strPageTemp, i);
                        }
                    }
                    SBPage.AppendFormat(strCurrentTemp, PageNum);

                }
                else//若当前页数不等于1且不等于总页数
                {
                    if (1 < PageNum && PageNum <= 10)//若总页数大于1小于等于10
                    {
                        SBPage.Append(strFirstTemp);
                        SBPage.Append(strFrontTemp);
                        for (int i = 1; i <= PageNum; i++)
                        {
                            if (PageIndex == i)
                            {
                                SBPage.AppendFormat(strCurrentTemp, i);
                            }
                            else
                            {
                                SBPage.AppendFormat(strPageTemp, i);
                            }
                        }
                        SBPage.Append(strNextTemp);
                        SBPage.Append(strLastTemp);

                    }
                    else//若总页数大于10
                    {
                        if (1 < PageIndex && PageIndex <= 5)//若当前页数大于1且小于等于5
                        {
                            SBPage.Append(strFirstTemp);
                            SBPage.Append(strFrontTemp);
                            for (int i = 1; i <= 10; i++)
                            {
                                if (PageIndex == i)
                                {
                                    SBPage.AppendFormat(strCurrentTemp, i);
                                }
                                else
                                {
                                    SBPage.AppendFormat(strPageTemp, i);
                                }
                            }
                            SBPage.Append(strNextTemp);
                            SBPage.Append(strLastTemp);

                        }
                        else//若当前页数大于5
                        {
                            if (5 < PageIndex && PageIndex <= (PageNum - 5))//若当前页数大于5且小于总页数-5
                            {
                                SBPage.Append(strFirstTemp);
                                SBPage.Append(strFrontTemp);
                                for (int i = (PageIndex - 4); i <= (PageIndex + 5); i++)
                                {
                                    if (PageIndex == i)
                                    {
                                        SBPage.AppendFormat(strCurrentTemp, i);
                                    }
                                    else
                                    {
                                        SBPage.AppendFormat(strPageTemp, i);
                                    }
                                }
                                SBPage.Append(strNextTemp);
                                SBPage.Append(strLastTemp);

                            }
                            else//若当前页数小于总页数-5
                            {
                                SBPage.Append(strFirstTemp);
                                SBPage.Append(strFrontTemp);
                                for (int i = (PageNum - 9); i <= PageNum; i++)
                                {
                                    if (PageIndex == i)
                                    {
                                        SBPage.AppendFormat(strCurrentTemp, i);
                                    }
                                    else
                                    {
                                        SBPage.AppendFormat(strPageTemp, i);
                                    }
                                }
                                SBPage.Append(strNextTemp);
                                SBPage.Append(strLastTemp);
                            }
                        }
                    }
                }
            }

            #endregion
        }

最后把得到的各种数据添加到声明的list里,并返回给前台JS处理

     

        list.Add(SB.ToString());

        list.Add(SBPage.ToString());

        list.Add(PageNum.ToString());

        list.Add(ProductCount.ToString());

     return list;

 

步骤C:前台分页调用

 

同步步骤B2中的代码已经看到返回的HTML元素中已经有了onclick事件,调用的是前台方法getList

 

我们来看看这个方法的代码:

function getList(pageIndex) {
            $.ajax({
                type: "POST",
                url: "/cnblog/ajax.aspx/LoadProduct",
                data: "{'PageIndex':'" + pageindex + "','key':'" + decodeURIComponent($.request("key")) + "'}", //搜索关键字,如果没有则为空
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function (result) {
                    $(".productslist").html(result.d[0]);
                    $(".paginator").html(result.d[1]);
                    $(".pageCount").html(result.d[2]);
                    $(".productCount").html(result.d[3]);
                },
                error: function (result) {

                }
            });
            return false;//一定要加return false。在ie里一个超链接有onclick事件也有href属性,如果不加return false 点击的时候会触发事件后再跳转
        }

参数为pageIndex ,既页数 ,所以当点击返回的页数连接时会调用这个方法,并且把页数及搜索关键词传过去,传过去之后得到的结果即为步骤B中LoadProduct方法的返回值。

我们来看看效果吧!

注意截图上的文字解释:

 

 

 

 

演示地址

演示地址

 

 

 

posted on 2013-04-25 19:02  libero1890  阅读(1687)  评论(10编辑  收藏  举报

导航