上一篇文章介绍了如何使用JavaScript代码在客户端实现列表的分页浏览功能,本文将提高一些难度,会实现表格的分页,并可以在每一行添加数据的操作链接。
首先来看数据表格的未分页状态,如下图所示。
在实现表格分页浏览及添加行数据操作链接之前,约定如下:
下面是完整的页面代码。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> <style> #result { min-height:300px; } .table_data { width:100%; } .table_data tr:nth-child(odd) { background-color: lightblue; } .table_data tr:nth-child(even) { background-color: lightyellow; } .table_data tr th{ background-color:#ccc; } .table_data tr td { text-align: center; } .table_data tr td a{ font-size:0.9em; margin-left:0.5em; } .tablePageNavi { text-align: center; margin-top: 2em; } .tablePageNavi a { font-size: 0.9em; margin-left: 0.5em; margin-right: 0.5em; } </style> </head> <body> <div id="result"> <table id="table1" class="table_data"> <tr><th>ID</th><th>用户名</th><th>姓名</th><th>性别</th><th>状态</th></tr> <tr rowdata="1"><td>1</td><td>user01</td><td>测试一</td><td>1</td><td>0</td></tr> <tr rowdata="2"><td>2</td><td>user02</td><td>测试二</td><td>1</td><td>0</td></tr> <tr rowdata="3"><td>3</td><td>user03</td><td>测试三</td><td>1</td><td>1</td></tr> <tr rowdata="4"><td>4</td><td>user04</td><td>测试四</td><td>1</td><td>0</td></tr> <tr rowdata="5"><td>5</td><td>user05</td><td>测试五</td><td>2</td><td>0</td></tr> <tr rowdata="6"><td>6</td><td>user06</td><td>测试六</td><td>2</td><td>1</td></tr> <tr rowdata="7"><td>7</td><td>user07</td><td>测试七</td><td>2</td><td>0</td></tr> <tr rowdata="8"><td>8</td><td>user08</td><td>测试八</td><td>2</td><td>0</td></tr> <tr rowdata="9"><td>9</td><td>user09</td><td>测试九</td><td>0</td><td>1</td></tr> <tr rowdata="10"><td>10</td><td>user10</td><td>测试十</td><td>0</td><td>1</td></tr> </table> </div> </body> </html> <script> // 初始化 function tablePageInit(id, rowPerPage) { let tbl = document.getElementById(id); if (tbl === undefined) return false; let rows = tableRows(id); if (rows === null) return false; rowPerPage = parseInt(rowPerPage); if (isNaN(rowPerPage) || rowPerPage < 1) return false; // 计算总页数,不包含第一行的列名 let dataRowCount = rows.length - 1; let pageCount = Math.floor(dataRowCount / rowPerPage); if (dataRowCount % rowPerPage > 0) pageCount++; // 显示导航和数据 let s = []; s.push("<div id='tablePageNavi' class='tablePageNavi'>"); // 首页 s.push(`<a href="javascript:tableShowPage('${id}',1);">首页</a>`); // 上一页 s.push(`<a href="javascript:tablePreviousPage('${id}');">上一页</a>`); // 页选择列表,当前页/总页数 s.push(`<select id="${id}_curpage" onchange="tableShowPage('${id}',this.value);">`); for (let i = 1; i <= pageCount; i++) { s.push(`<option value="${i}">${i}</option>`); } s.push(`</select>/<span id="${id}_pagecount">${pageCount}</span>`) // 下一页 s.push(`<a href="javascript:tableNextPage('${id}');">下一页</a>`); // 末页 s.push(`<a href="javascript:tableLastPage('${id}');">末页</a>`); // 隐藏数据,每页多少行 s.push(`<input id="${id}_rpp" type="hidden" value="${rowPerPage}">`); // s.push("</div>"); tbl.parentElement.innerHTML += s.join(""); // 显示第1页 tableShowPage(id, 1); // return true; } // 添加行记录操作链接,约定每行tr元素的rowdata属性为记录主数据 // template中的{#}替换为记录主数据 function tableAddRowOpt(id, template) { let rows = tableRows(id); rows[0].innerHTML += "<th>操作</th>"; let rowData = ""; let s = ""; for (let i = 1; i < rows.length; i++) { rowData = rows[i].getAttribute("rowdata"); s = template.replace(/{#}/g, rowData); rows[i].innerHTML += `<td>${s}</td>`; } } // 返回表元素的所有行,约定第1行为列名 function tableRows(id) { let tbl = document.getElementById(id); let rows = tbl.getElementsByTagName("tr"); if (rows.length > 0) return rows; else return null; } // 读取当前页 function tableCurPage(id) { let sel = document.getElementById(id + "_curpage"); return parseInt(sel.value); } // 读取总页数 function tablePageCount(id) { let span = document.getElementById(id + "_pagecount"); return parseInt(span.innerText); } // 读取每页多少行 function tableRowPerPage(id) { let inp = document.getElementById(id + "_rpp"); return parseInt(inp.value); } // 显示指定的页 function tableShowPage(id, page) { let rowPerPage = tableRowPerPage(id); let rows = tableRows(id); // 计算显示页行索引,0为标题行 let min = (page - 1) * rowPerPage + 1; // 当前页不包含max索引行 let max = min + rowPerPage; if (max > rows.length) max = rows.length; // for (let i = 1; i < min; i++) rows[i].style.display = "none"; for (let i = min; i < max; i++) rows[i].style.display = "table-row"; for (let i = max; i < rows.length; i++) rows[i].style.display = "none"; // 同步当前页列表 let sel = document.getElementById(id + "_curpage"); sel.value = page; } // 上一页 function tablePreviousPage(id) { let curPage = tableCurPage(id); let nextPage = curPage - 1; if (nextPage < 1) nextPage = 1; tableShowPage(id, nextPage); } // 下一页 function tableNextPage(id) { let curPage = tableCurPage(id); let pageCount = tablePageCount(id); let nextPage = curPage + 1; if (nextPage > pageCount) nextPage = pageCount; tableShowPage(id, nextPage); } // 末页 function tableLastPage(id) { tableShowPage(id, tablePageCount(id)); } // 测试代码 tablePageInit("table1", 3); tableAddRowOpt("table1", `<a href="Edit.aspx?id={#}">编辑</a><a href="Per.aspx?id={#}">权限</a>`); </script>
其中,style元素中定义了一些必要的CSS样式。id属性为result的div元素中定义了一个table元素,其id为table1,包含一行列名和10行数据。script元素中定义了表格分页和添加行记录操作链接的函数,最后是测试调用。页面显示效果如下图所示。
下面关注script元素代码,JavaScript代码中包括了表格分页和添加行记录操作链接的一系列函数,下面分别讨论。
tablePageInit(id, rowPerPage)函数,表格分页浏览初始化。函数中,首先检查表格元素、数据行和每页行数的正确性,如果检查不通过,则函数返回false。然后,计算了总页数(pageCount)。接下来是导航栏的定义,包括显示首页,调用tableShowPage(id,1);显示上一页,调用tablePreviousPage(id);显示下一页,调用tableNextPage(id);显示末页,调用tableLastPage(id)。在“上一页”和“下一页”链接之间还显示了当前页的选择列表(<id>_curpage)和显示总页数的span元素(<id>_pagecount),其中,在列表中选择当前页时会调用tableShowPage(id,page)函数显示此页数据。在“末页”链接之后,使用隐藏的input元素(<id>_rpp)显示了每页显示多少行的数据。最后,将导航栏代码添加到表格下面,并显示第一页的数据。初始化完成后,函数会返回true。
tableAddRowOpt(id, template)函数,用于添加每行记录的操作链接。参数id指定table元素的id,参数template指定行记录操作的模板代码,其中的{#}会替换为行数据,即tr元素的rowdata属性值。函数中,在第一行的最后添加th元素,显示内容为“操作”;之后,在所有数据行最后添加td元素,并将替换行数据之后的template内容添加到单元格,如模板为“<a href='Edit.aspx?id={#}'>编辑</a>”,行数据为1,则单元格中显示的内容就是“<a href='Edit.aspx?id=1'>编辑</a>”。
tableRows(id)函数,返回指定id的表格中的所有tr元素集合,即所有行的集合。请注意,如果tr元素数量为0,则函数返回null。
tableCurPage(id)函数,从id属性为“<id>_curpage”的select元素读取当前页数据,返回整数值。
tablePageCount(id)函数,从id属性为“<id>_pagecount”的span元素中读取总页数,返回整数值。
tableRowPerPage(id)函数,从id属性为“<id>_rpp”的隐藏input元素中读取每页显示多少行,返回整数值。
tableShowPage(id, page)函数,显示指定页的数据行。函数中会通过指定的页码(page)、每页显示多少行和总行数计算当前显示的数据行;请注意,数据行是从第2行(索引1)开始的;表的第一行为列名,总是会显示。显示指定的页后,还会指定当前页列表同步当前页数据。
tablePreviousPage(id)函数,显示当前页的前一页,如果上一页小于1则显示第一页。
tableNextPage(id)函数,显示当前面的下一页,如果下一页大于总页数则显示最后一页。
tableLastPage(id)函数,显示最后一页。
代码的最后为测试代码,tablePageInit()函数中指定表格id为"table1",每页显示3行数据。使用tableAddRowOpt()函数添加行记录操作链接的模板为"<a href="Edit.aspx?id={#}">编辑</a><a href="Per.aspx?id={#}">权限</a>",如果行数据为1,则行的最后添加的td元素中的内容就是"<a href="Edit.aspx?id=1">编辑</a><a href="Per.aspx?id=1">权限</a>"。