JavaScript实现列表分页、查询等功能

场景一

​ 某一天,后端开发同事说:这个列表的数据不是特别多,我一次传给你,你自己处理一下这些数据,OK不OK?

场景二

​ 项目经理:项目这里要做个列表页,不单独开发接口了,实现一下查询的功能就可以了。

​ 大头答:有获取数据的接口吗?模糊查询还是精确查询?查询条件是多选还是单选?用UI组件库吗?

​ 项目经理答:数据纯手工造,模糊查询嘛,一个或多个查询都可以晒!不合适。

​ ······

​ 细想片刻,我擦,还有分页要做?

​ 捋捋思路,不用Element-UI组件库是吧?要实现列表页,主要就是实现分页以及查询噶,根据页码、是否查询来动态渲染页面数据,应该不是太难,好,开干!

需求分析

​ 列表分页倒是没有什么太大的问题,根据设置的当前页大小拆分这个数组返回相对应的数组就行,引入查询之后呢?区别无非在于拆分的这个数组有所变化对吧,这是根据查询生成的一个新的数组,其他按部就班的来就没问题了。

​ 参考Element-UI列表和分页的实现,通常,我们是将当前页、页面大小、查询条件一起返回后端,页面响应对应的数据就完成了。因此,这里我们可以封装一个方法就能实现这一需求,对吧!

功能实现

分页

​ 分页一般来说,主要包括:上下页切换的功能、点击页码跳转某一页的功能以及直达某一页的功能,那目标就是正确的显示当前页的数据以及分页中的页码及其他数据,然后再注意一些其他的细节就可以了。

  1. 创建对应的html结构

    html 复制代码
     <div class="list_page">
       <span class="page_prev" id="page_prev">
       	<a>上一页</a>
       </span>
       <span class="page_next" id="page_next">
       	<a>下一页</a>
       </span>
       <span class="page_text">跳转到</span>
       <span class="gopage">
       	<input type="text" value="1" id="gopage" name="gopage">
       </span>
       <span class="list_page_span">GO</span> </div>
     </div>

    为啥没有页码?查询和不查询的页码肯定是分情况讨论的啊,所以页码由我们动态生成DOM去实现;

  2. 生成页码及表格页面

    1. 确定分页大小、总页数

      javascript 复制代码
      <script>
        	// 页面大小为15条,获取总页数
      	window.totalPage = Math.ceil(pageData.length / 15)
      <script>
    2. 获取对应分页上的数据

      javascript 复制代码
      <script>
        	// 先获取当前页第一条数据和最后一条数据角码,进而分割字符串
          var startIndex = (pageIndex - 1) * 15;
          var endIndex = startIndex + 15;
          var tableData = pageData.slice(startIndex, endIndex)
      <script>
    3. 页面数据渲染

      ​ 渲染数据的时候,咱是否应该处理掉当前页面上的表格数据,因此,首先清空表格里面原有的数据;之后给定表头的列表数据;然后我们就来循环渲染上面我们获取到的tableData;因为我这里的需求是表格是斑马条纹的样式,因此这里做了一个判断,进而得到奇数和偶数两个不同属性的数据;最后填充表格数据,就完成了表格对应的页面。

      javascript 复制代码
      <script>
          // 先获取当前页第一条数据和最后一条数据角码,进而分割字符串
          const table = document.getElementById("txl_table")
          table.innerHTML = ''
          var tableHtml = '<tr><th scope="col" style="width: 348px;">商品名称</th><th scope="col" style="width: 287px;">所属品类</th><th scope="col" style="width: 465px;">订购电话</th></tr>'
          for (let i = 0; i < tableData.length; i++) {
          if (i % 2 === 0) {
            tableHtml += '<tr>' + '<td align="center">' + tableData[i].unitName + '</td><td align = "center" > ' + tableData[i].jobIDName + '</td><td align="center">' + tableData[i].telephone + '</td>' + '</tr>'
            } else {
            tableHtml += '<tr class="even">' + '<td align="center">' + tableData[i].unitName +
            '</td><td align = "center" > ' + tableData[i].jobIDName + '</td><td align="center">' + tableData[i].telephone + '</td>' + '</tr>'
            }
          }
          table.innerHTML = tableHtml
      	// 给页面直达的span标签赋值,也相当于是显示第几页
      	document.getElementById('gopage').value = pageIndex
      <script>
    4. 分页数据的渲染

      ​ 这里特别说明一下分页数据的渲染:假定我们有200条数据,分页大小为15,那么我们就有14页的数据,页码都要展示出来吗?那肯定是不需要的,展示五个页码就比较合适(如果对当前页页码有样式处理,奇数最为合适),当前页居中,对吧?如果是第九页,那我们就展示第七页、第八页、第九页、第十页、第十一页;第一页的话,就是一到五;第二页的话,也是一到五,因为没有-1页;第三页,也是一到五,且刚好居中满足我们的需求;以此类推,到第十二页的时候,对应的就是十到十四页对吧;再然后呢?为满足咱们的需求,第十三页和第十四页是不是应该只能往前推了呢,即十到十四。因此这里就是三种情况了,因此在渲染分页页面的时候就需要进行相应的一个判断;不过这里还有一种情况我们没有考虑到,如果一共就一页或者两页数据呢?这里即又是一种新的情况。

      ​ 因此,实现分页的时候,我们还要考虑四种情况。

      1. 调用同一个方法,因此,每次渲染对应数据的时候,我们应先清空之前的页面数据;

        javascript 复制代码
        <script>
          // 查找页面上所有ID为"makeSpan"的span标签,然后删除
          var spanElements = document.querySelectorAll('#makeSpan');
          if (spanElements.length > 0) {
            spanElements.forEach(function (element) {
              element.remove();
            });
          }
          pageIndexHtmls = ''
        </script>
      2. 判断并创建对应的分页页面结构

        ​ 判断的时候,我们始终会对是否为当前页进行一个判断,为减少重复代码,这里封装了一个公共的方法去判断是否为当前页,是,我们就加上"active"的属性值,否,则不添加;

        javascript 复制代码
        <script>
          // 是否为当前页
          function generatePageIndexHtml(x, pageIndex) {  
            var pageIndexHtml = ''  
            if (x == pageIndex) {  
              pageIndexHtml += '<span class="active" id="makeSpan" onclick="makePage(checkInputValues(), ' + x + ')">' + x + '</span>';  
            } else {  
              pageIndexHtml += '<span id="makeSpan" onclick="makePage(checkInputValues(), ' + x + ')">' + x + '</span>';  
            }  
            return pageIndexHtml;  
          }
        </script>
        javascript 复制代码
        <script>
          if(totalPage >= 3) {
            if(totalPage - 2 >= pageIndex && pageIndex > 3) {
              for (let x = pageIndex - 2; x <= pageIndex + 2; x++) {
                pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
              }
            }
        
            if(pageIndex > totalPage - 2) {
              for (let x = totalPage - 4; x <= totalPage; x++) {
                pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
              }
            }
            if(pageIndex <= 3) {
              for (let x = 1; x <= 5; x++) {
                pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
              }
            }
          } else {
            for (let x = 1; x <= totalPage; x++) {
              pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
            }
          }
          // 在id为page_prev的span标签后添加这段html结构,即切换至上一页的按钮后添加
          document.getElementById('page_prev').insertAdjacentHTML('afterend', pageIndexHtmls);
        </script>
  3. 上一页及下一页

    ​ 通过监听上一页和下一页是否有点击事件来实现,如果当前页不是第一页,则上一页即自减;反之,下一页也亦是如此;

    javascript 复制代码
    <script>
        document.getElementById('page_prev').addEventListener('click', function () {
      	  // 获取当前页码
          let currentPage = document.getElementById('gopage').value;
            if (currentPage > 1) {
                currentPage--;
                // makePage()是创建页面的方法,checkInputValues()是判断是否是查询的方法,后面会提到
                makePage(checkInputValues(), currentPage)
            }
        });
    
        document.getElementById('page_next').addEventListener('click', function () {
          let currentPage = document.getElementById('gopage').value;
            if (currentPage < totalPage) {
                currentPage++;
                makePage(checkInputValues(), currentPage)
            }
        });
    </script>
  4. 点击页码跳转

    ​ 因为我们在创建页面结构的时候,给每一个页面加上了对应的点击事件,即onclick="makePage(checkInputValues(), ' + x + ')",这里就不用进行其他的数据处理了;

  5. 页码直达

    ​ 在前面,我们给定了一个跳转的标签,即<span class="list_page_span">GO</span>,在这里,我们定义一个方法,获取元素的值,从而创建对应的页面,即实现跳转直达某页的需求;这里还可以进行一些细节上的处理,比如说,用户没有输入的时候,点击这里,即仍是刷新当前页的数据,就应该禁用,在这段js代码中加上一个判断就可以了。

    javascript 复制代码
    <script>
        function goToPage() {
            toPage = document.getElementById('gopage').value;
            makePage(checkInputValues(), Number(toPage))
        }
    </script>
查询

​ 在前面的分析中,我们可以知道,查询的数组就是未查询的分页数组过滤之后的新数组,之后创建页面的逻辑也是一样,因此在整体封装创建页面的方法之前,我们可以添加一个字段去判断是否进行了查询,是,就用新数组,否,就用原始的数组。

  1. 创建三个查询条件的输入框,即查询搜索的页面结构;

    html 复制代码
    <table width="100%"  cellspacing="0" cellpadding="0" border="0" class="tablelists topfrom">
      <tbody>
        <tr>
          <th>商品名称:</th>
          <td class="pa_l_10"><input type="text" value="" name="SearchKey" id="unitName" class="input2"></td>
          <th>所属品类: </th>
          <td class="pa_l_10"><input type="text" value="" name="SearchKey" id="jobIDName" class="input2"></td>
          <th>订购电话: </th>
          <td class="pa_l_10"><input type="text" value="" name="SearchKey" id="telephone" class="input2"></td>
          <td style="text-align: center;"><input type="submit" value="搜索" class="btn_submit" onclick="makePage(checkInputValues(), 1)" /></td>
        </tr>
      </tbody>
    </table>

  2. 是否查询

    javascript 复制代码
    <script>
    	// 获取输入框是否有值,有的话,就返回true
     function checkInputValues() {
         const unitName = document.getElementById('unitName').value;
         const jobIDName = document.getElementById('jobIDName').value;
         const telephone = document.getElementById('telephone').value;
         var hasValues = [unitName, jobIDName, telephone].some(function (value) {
             return value !== '';
         });
         return hasValues;
     }
    </script>
  3. 模糊查询(过滤数组)

    javascript 复制代码
    <script>
        const unitName = document.getElementById('unitName').value;
        const jobIDName = document.getElementById('jobIDName').value;
        const telephone = document.getElementById('telephone').value;
        const result = array.filter(item => {
          return (item.unitName.includes(unitName) && item.jobIDName.includes(jobIDName) &&
                  item.telephone.includes(telephone));
        });
    	// 赋值给表格数据
        pageData = result
    </script>

拓展

搜索优化

​ 当前实现的搜索功能是通过传入参数点击搜索实现的,单点击页面好像有点呆,想高级一点,或者说至少加上回车键入搜索吧,不难,事件传入方法即可实现;模拟远程检索(假装数据的动态的),可以吗?动态监听输入框是否有变化,调用setTimeout()方法,设置0.5秒后,触发创建页面的方法就可以了。

javascript 复制代码
<script>
    // 动态监听查询条件的变化
    function handleValueChange() {  
        setTimeout(makePage(checkInputValues(), 1), 500);   
    }
    document.getElementById('unitName').addEventListener('input', handleValueChange);  
    document.getElementById('jobIDName').addEventListener('input', handleValueChange);  
    document.getElementById('telephone').addEventListener('input', handleValueChange);
</script>
完整代码
javascript 复制代码
     // 表格样式
     <style>
         .txl_table{ margin-top:20px;}
         .txl_table th{ background:#015fa7; height:40px; text-align:center; color:#fff; font-weight:normal; line-height:40px;}
         .txl_table td{ height:40px; line-height:40px;}
         .txl_table tr.odd{ background:#eef6fc;}
         .txl_table tr.even{ background:#eef6fc;}
         .txl_table tr td{ padding-left:10px;}
         .txl_table tr:hover{ background:#e1effa;}
     </style>
     
     <script>
       // 判断是否为当前页,同时创建分页的页面数据
     	function generatePageIndexHtml(x, pageIndex) {  
           var pageIndexHtml = ''  
           if (x == pageIndex) {  
               pageIndexHtml += '<span class="active" id="makeSpan" onclick="makePage(checkInputValues(), ' + x + ')">' + x + '</span>';  
           } else {  
               pageIndexHtml += '<span id="makeSpan" onclick="makePage(checkInputValues(), ' + x + ')">' + x + '</span>';  
           }  
           return pageIndexHtml;  
       }
     </script>
     
     <script>
       // 创建页面
       function makePage(isSearch, pageIndex) {
       	   // 初始化将要渲染的页面数据
           pageData = []
           // 判断是否在进行查询,根据情况为页面原始数据赋值
           if (isSearch) {
               const unitName = document.getElementById('unitName').value;
               const jobIDName = document.getElementById('jobIDName').value;
               const telephone = document.getElementById('telephone').value;
               const result = array.filter(item => {
                   return (item.unitName.includes(unitName) && item.jobIDName.includes(jobIDName) &&
                       item.telephone.includes(telephone));
               });
               pageData = result
           } else {
               pageData = array
           }
           // 创建分页
           window.totalPage = Math.ceil(pageData.length / 15)
           var spanElements = document.querySelectorAll('#makeSpan');
           if (spanElements.length > 0) {
               spanElements.forEach(function (element) {
                   element.remove();
               });
           }
           pageIndexHtmls = ''
           if(totalPage >= 3) {
             if(totalPage - 2 >= pageIndex && pageIndex > 3) {
             	for (let x = pageIndex - 2; x <= pageIndex + 2; x++) {
                 	pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
               }
             }
             if(pageIndex > totalPage - 2) {
             	for (let x = totalPage - 4; x <= totalPage; x++) {
                   pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
               }
             }
             if(pageIndex <= 3) {
             	for (let x = 1; x <= 5; x++) {
                   pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
               }
             }
           } else {
           	for (let x = 1; x <= totalPage; x++) {
                   pageIndexHtmls += generatePageIndexHtml(x, pageIndex)
               }
           }
           document.getElementById('page_prev').insertAdjacentHTML('afterend', pageIndexHtmls);
           // 创建列表数据
           var startIndex = (pageIndex - 1) * 15;
           var endIndex = startIndex + 15;
           var tableData = pageData.slice(startIndex, endIndex)
           const table = document.getElementById("txl_table")
           table.innerHTML = ''
           var tableHtml = '<tr><th scope="col" style="width: 348px;">商品名称</th><th scope="col" style="width: 287px;">所属品类</th><th scope="col" style="width: 465px;">订购电话</th></tr>'
           for (i = 0; i < tableData.length; i++) {
               if (i % 2 === 0) {
                   tableHtml += '<tr>' + '<td align="center">' + tableData[i].unitName + '</td><td align = "center" > ' +
                       tableData[i].jobIDName + '</td><td align="center">' + tableData[i].telephone + '</td>' + '</tr>'
               } else {
                   tableHtml += '<tr class="even">' + '<td align="center">' + tableData[i].unitName +
                       '</td><td align = "center" > ' + tableData[i].jobIDName + '</td><td align="center">' + tableData[i]
                       .telephone + '</td>' + '</tr>'
               }
           }
           table.innerHTML = tableHtml
           document.getElementById('gopage').value = pageIndex
       }
   </script>

   <script>
       // 判断用户是否在进行查询的方法
       function checkInputValues() {
           const unitName = document.getElementById('unitName').value;
           const jobIDName = document.getElementById('jobIDName').value;
           const telephone = document.getElementById('telephone').value;
           var hasValues = [unitName, jobIDName, telephone].some(function (value) {
               return value !== '';
           });
           return hasValues;
       }
   </script>
     
     <script>
       // 初始化页面
       let array = [  
         { unitName: '苹果', jobIDName: '水果', telephone: '028-12345678' }, 
         	······
         { unitName: '电烤箱', jobIDName: '家电', telephone: '028-87654321' }
       ]
       makePage(checkInputValues(), 1)
     </script>
     
   <script>
       // 监听上一页
       document.getElementById('page_prev').addEventListener('click', function () {
         let currentPage = document.getElementById('gopage').value;
           if (currentPage > 1) {
               currentPage--;
               makePage(checkInputValues(), currentPage)  
           }
       })
       // 监听下一页
       document.getElementById('page_next').addEventListener('click', function () {
         let currentPage = document.getElementById('gopage').value;
           if (currentPage < totalPage) {
               currentPage++;
               makePage(checkInputValues(), currentPage)
           }
       })
       // 直达目标页方法实现
       function goToPage() {
           toPage = document.getElementById('gopage').value;
           makePage(checkInputValues(), Number(toPage))
       }
   </script>

相关推荐
光影少年14 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
Rattenking19 分钟前
React 源码学习01 ---- React.Children.map 的实现与应用
javascript·学习·react.js
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
别拿曾经看以后~3 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
川石课堂软件测试3 小时前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
JerryXZR3 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
problc4 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter
Gavin_9154 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼5 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
待磨的钝刨6 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json