JS分页实现:同步与异步方案对比及搜索条件处理

作者:代码拾荒时间:2026-10-22 08:17:08浏览:482

本文对比了前端一次性加载与后端分页的性能差异,重点解析后端同步分页中搜索条件丢失的问题及Session解决方案。随后深入讲解基于Ajax的异步分页实现,通过全局变量保存搜索状态,解决了刷新页面后搜索条件重置的痛点,提供了完整的代码逻辑与优化思路。

分页技术概述

分页技术主要划分为后端分页与前端分页两种模式。

前端分页的局限性

前端分页

前端分页的核心逻辑是将所有数据一次性从服务器获取至客户端,随后利用JavaScript在本地进行分页展示。这种方式存在明显缺陷:假设数据库表dbgoods中存储了99999万条数据,若执行查询语句 select *from dbgoods where 1=1 并将结果集通过List<goods>list 进行接收,服务端需将海量数据传输至前端。这不仅导致巨大的下载流量(增加成本),还会给服务器带来沉重的处理压力。

后端分页与同步实现

后端分页

后端分页策略要求每次请求仅查询当前页的数据。以MySQL数据库为例,若需查询从第一条开始的后8条记录,具体操作如下:


select * from dbgoods order by id limit 0,8;

后端同步分页

其实现原理是设计一个Bean对象来封装分页相关的信息,


public class PageBean{
 private long total;  //总记录数
 private List<T> list; //结果集
 private int pageNum; // 第几页
 private int pageSize; // 每页记录数
 private int pages;  // 总页数
 private int size;  // 当前页的数量 <= pageSize,该属性来自ArrayList的size属性

在首次加载页面时,系统默认加载第一页的分页数据:

分页技术概述

需要特别注意的是

以往在编写SQL语句以获取总记录数时,常见的做法是:


select *from dbgoods ;
//用Lits<goods> lists去存储 得到的数据,如果数据有几万条,
//为了得到一个数字,去开辟这么大的空间,实属浪费
PageBean page=new PageBean();
page.setTotal=lists.size();

实际上,更规范的实现方式应为:


select count(*) from dbgoods where 1=1 ;
//查询语句返回的是一个表的总记录数,int型,
//where 1==1是为了查询搜索,做sql语句拼接

同步分页的实现流程为:从JSP界面传递currentpage参数至Servlet,Servlet通过request对象获取该参数,经DAO层查询数据库后,将数据返回并跳转至JSP界面展示。

从浏览器视角看,界面交互路径为:jsp--->servlet----->jsp(发生页面跳转),这种体验并不友好。

若界面包含搜索框,在执行搜索分页时,点击搜索按钮后,待数据传回JSP界面,页面已完全刷新,导致搜索框内的文本内容丢失。为解决此问题,需在点击搜索时将文本框的值一并放入request请求中发送给Servlet,再由Servlet传递至新的JSP页面。这一过程实现起来极为繁琐。

分页技术概述

同步分页搜索条件处理方案

针对上述问题,主要有两种解决思路:

(1)构建两个界面布局相同的页面:一个用于展示全量数据的分页,另一个用于展示搜索结果的分页。当点击查询时,获取数据后由另一个页面(其下一页点击事件指向执行搜索逻辑)进行显示。

(2)利用Session存储:当点击搜索查询时,将搜索条件保存至Session中。点击下一页时,判断Session值:若为空,则执行全量数据的下一页逻辑;若不为空,则取出Session值作为查询条件,执行带有搜索条件的分页语句。此方法较为繁琐,且Session的销毁机制难以精确控制,容易引发Bug。

综上所述,采用同步方式实现分页功能,往往伴随诸多不便与体验缺陷。

Ajax异步分页实现与优化

Ajax异步分页


//jsp界面一个函数,传递查询页码,绘制表格
 function InitTable(currentpage)
     {
      $.ajax({
       type:"get",
       url:"CustomServlet?type=search&currentpage="+currentpage,
       async:true,
       dataType:"json",
       success:function(data)
       {
        DrawTable(data); //绘制表格
       }
      });
     }
function DrawTable(data) //根据传递过来的json绘制表格
     {
      //给总页数赋值
      $("#custom_all").text(data.pagelist.total);
     //给当前页赋值
$("#custom_currunt_page").text(data.pagelist.pageNum);
     //给总页数赋值
 $("#custom_all_page").text(data.pagelist.pages);
      var _th="<th><input id='cb_all' type='checkbox'></th>"
      +"<th>ID</th>"
      +"<th>客户名称</th>"
      +"<th>公司名称</th>"
      +"<th>联系人</th>"
      +"<th>性别</th>"
      +"<th>联系电话</th>"
      +"<th>手机</th>"
      +"<th>QQ</th>"
      +"<th>电子邮箱</th>"
      +"<th>通讯地址</th>"
      +"<th>创建时间</th>";
      document.getElementsByTagName("tbody")[0].innerHTML=_th;
       for(var i=0;i<data.pagelist.list.length;i++)
       {
        var customerCreatetime= format(data.pagelist.list[i].customerCreatetime, 'yyyy-MM-dd');
        var _tr=document.createElement('tr');
        msg="<td><input type='checkbox'></td><td>"+data.pagelist.list[i].customerId+"</td><td>"+data.pagelist.list[i].customerName+"</td><td>"+data.pagelist.list[i].customerCompanyname+"</td><td>"+data.pagelist.list[i].customerContactname+"</td><td>"+data.pagelist.list[i].customerSex+"</td><td>"+data.pagelist.list[i].customerTelephone+"</td><td>"+data.pagelist.list[i].customerPhone+"</td><td>"+data.pagelist.list[i].customerQq+"</td><td>"+data.pagelist.list[i].customerEmail+"</td><td>"+data.pagelist.list[i].customerAddress+"</td><td>"+customerCreatetime+"</td>"
       _tr.innerHTML=msg;         
        document.getElementsByTagName("tbody")[0].appendChild(_tr);
       }
     }

在初次加载页面时,默认调用初始化函数:


//初始化表格
      InitTable(1);

需要特别强调的是,接下来的内容是核心重点:

在执行搜索操作时,定义一个名为mydata的全局变量,其作用域覆盖整个页面。


var mydata="";

接下来查看点击搜索按钮的事件处理代码:


btns.eq(1).click( //搜索按钮点击事件
          function()
         {
      //custom_dialog_form是搜索的form表单,将其搜索条件序列化后赋值给一个全局变量     mydata=$("#custom_dialog_form").serialize();
           $.ajax({
            type:"post",
            url:"CustomServlet?type=search&currentpage=1",
            async:true,
            dataType:"json",
            data:mydata, //传递数据
            success:function(data)
            {
             DrawTable(data);
             $("#custom_dialog").css("display","none");
            }
           });
         }
          );

针对同步分页中搜索后下一页仍访问全量数据的问题,异步方案提供了更好的解决思路:


 function InitTable(currentpage) //无搜索条件下的查询,传递一个页码
     {
      $.ajax({
       type:"get",
       url:"CustomServlet?type=search&currentpage="+currentpage,
       async:true,
       dataType:"json",
       success:function(data)
       {
        DrawTable(data);
       }
      });
     }
     function InitTableSearch(currentpage)//有搜索添加的查询,传递页码
     {
       $.ajax({
        type:"post",
        url:"CustomServlet?type=search&currentpage="+currentpage,
        async:true,
        dataType:"json",
        data:mydata,
        success:function(data)
        {
         DrawTable(data);
         $("#custom_dialog").css("display","none");
        }
       });
     }
//下一页
      $("#custom_btn_next").click(
        function ()
        {
         var currentpage=$("#custom_currunt_page").text(); //获取页面的当前页的值
         var pages=$("#custom_all_page").text(); //获取总页数
         currentpage++;
         if(currentpage<=pages)
          {
          if(mydata=="") //判断全局变量mydata是否为空,空表示没有进行搜索查询
          {
          InitTable(currentpage);
          }
         else
          {
           InitTableSearch(currentpage); //进行条件搜索
          }
          }
        });

由于采用异步刷新机制,全局变量mydata中保存有搜索条件数据。即使用户手动刷新页面导致重新加载,mydata初始化为空,从而默认执行无条件搜索语句。这一机制巧妙解决了搜索与显示全部数据下一页之间的冲突,上一页、首页及尾页的逻辑同理可通。

总结

以上介绍了JS分页的实现方法,涵盖同步与异步两种模式,希望能为读者提供帮助。如有任何疑问,欢迎留言,小编会及时回复!

作者最新文章