纯JavaScript实现表格数据分页(仅保留上一页/下一页按钮)技术咨询
纯JavaScript实现表格分页(仅上下页按钮+自定义每页条数)
首先,我先帮你梳理现有代码的问题,然后提供一个完全符合需求的原生JS实现方案——不需要任何框架,支持选择10/20/50/100条或全部数据,仅保留上一页、下一页按钮。
现有代码的核心问题
- 变量作用域混乱:
nbElement未全局初始化,导致分页逻辑无法正确获取当前每页条数 - 分页判断逻辑错误:上下页跳转条件不符合数据范围,比如下一页未判断是否超出总数据长度
- 初始渲染缺失:数据加载完成后没有默认渲染第一页内容
- 全量数据处理缺失:选择"All"时没有正确展示所有数据,也未处理分页按钮状态
- 按钮状态未管理:第一页时上一页按钮应禁用,最后一页时下一页按钮应禁用,提升用户体验
修正后的完整实现
HTML代码(调整结构与闭合问题,添加基础样式)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Superheroes Database</title> <style> .tableau { border-collapse: collapse; width: 100%; margin-top: 20px; } .tableau th, .tableau td { border: 1px solid #ddd; padding: 8px; text-align: left; } .tableau th { background-color: #f2f2f2; } .btn-page { padding: 8px 16px; margin: 10px 5px; cursor: pointer; border: none; border-radius: 4px; background-color: #4CAF50; color: white; } .btn-page:disabled { cursor: not-allowed; opacity: 0.5; background-color: #ccc; } .custom-select, .selector { margin-right: 8px; } </style> </head> <body id="my-page"> <h1>Superheroes Database</h1> <br><br> <p>All of them in one place</p> <br><br> <input type="text" id="search" placeholder="Search for names..."> <form> <label class="selector" for="th-select">Search by...</label> <select id="th-list"> <option value="name">NAME</option> <option value="fullName">FULL NAME</option> <option value="race">RACE</option> <option value="intelligence">POWERSTATS (Intelligence)</option> <option value="strength">POWERSTATS (Strength)</option> <option value="speed">POWERSTATS (Speed)</option> <option value="durability">POWERSTATS (Durability)</option> <option value="power">POWERSTATS (Power)</option> <option value="combat">POWERSTATS (Combat)</option> <option value="gender">GENDER</option> <option value="placeOfBirth">PLACE OF BIRTH</option> <option value="alignment">ALIGNMENT</option> <option value="any" selected>ANY</option> </select> </form> <form> <label class="custom-select" for="maxRows-select">Elements per page: </label> <select id="maxRows"> <option value="10">10</option> <option value="20" selected>20</option> <option value="50">50</option> <option value="100">100</option> <option value="all">All</option> </select> </form> <p id="no-result"></p> <button class="btn-page" id="btn-previous" disabled> ← Previous </button> <button class="btn-page" id="btn-next"> Next → </button> <!-- TABLE CONSTRUCTION --> <table id="table" class="tableau" style="width:100%"> <thead> <tr> <th rowspan="2">Picture</th> <th rowspan="2">Name</th> <th rowspan="2">Full Name</th> <th rowspan="2">Powerstats</th> <th rowspan="2">Race</th> <th rowspan="2">Gender</th> <th rowspan="2">Height</th> <th rowspan="2">Weight</th> <th rowspan="2">Place of Birth</th> <th rowspan="2">Alignment</th> </tr> </thead> <tbody id="data"></tbody> </table> <script src="script.js"></script> </body> </html>
JavaScript代码(重写分页逻辑,修复所有问题)
// 全局状态管理 let characters = []; let currentOffset = 0; let itemsPerPage = 20; // 默认每页20条 const dataContainer = document.getElementById("data"); const prevBtn = document.getElementById("btn-previous"); const nextBtn = document.getElementById("btn-next"); const rowsSelector = document.getElementById("maxRows"); const noResultEl = document.getElementById("no-result"); // 异步加载英雄数据 async function fetchHeroes() { try { const response = await fetch('https://rawcdn.githack.com/akabab/superhero-api/0.2.0/api/all.json'); characters = await response.json(); console.log(`Loaded ${characters.length} heroes`); renderPage(); } catch (error) { noResultEl.textContent = "Failed to load hero data. Please try again later."; console.error("Fetch error:", error); } } // 渲染当前页内容 function renderPage() { if (characters.length === 0) return; let endIndex; // 处理全量数据的情况 if (itemsPerPage === "all") { endIndex = characters.length; prevBtn.disabled = true; nextBtn.disabled = true; } else { const perPage = parseInt(itemsPerPage); endIndex = currentOffset + perPage; // 确保不超出数据范围 if (endIndex > characters.length) endIndex = characters.length; // 更新按钮状态 prevBtn.disabled = currentOffset === 0; nextBtn.disabled = endIndex >= characters.length; } // 生成表格行,处理空字段 let tableHTML = ""; for (let i = currentOffset; i < endIndex; i++) { const hero = characters[i]; tableHTML += ` <tr> <td><img src="${hero.images.xs}" alt="${hero.name}"></td> <td class="hero-name">${hero.name}</td> <td class="hero-fullname">${hero.biography.fullName || "N/A"}</td> <td class="hero-powerstats"> Int: ${hero.powerstats.intelligence}, Str: ${hero.powerstats.strength}, Spd: ${hero.powerstats.speed}, Dur: ${hero.powerstats.durability}, Pwr: ${hero.powerstats.power}, Cmb: ${hero.powerstats.combat} </td> <td class="hero-race">${hero.appearance.race || "N/A"}</td> <td class="hero-gender">${hero.appearance.gender || "N/A"}</td> <td class="hero-height">${hero.appearance.height.join(", ")}</td> <td class="hero-weight">${hero.appearance.weight.join(", ")}</td> <td class="hero-placeOfBirth">${hero.biography.placeOfBirth || "N/A"}</td> <td class="hero-alignment">${hero.biography.alignment || "N/A"}</td> </tr> `; } dataContainer.innerHTML = tableHTML; } // 上一页按钮事件 prevBtn.addEventListener("click", () => { const perPage = parseInt(itemsPerPage); if (currentOffset - perPage >= 0) { currentOffset -= perPage; renderPage(); } }); // 下一页按钮事件 nextBtn.addEventListener("click", () => { const perPage = parseInt(itemsPerPage); const nextOffset = currentOffset + perPage; if (nextOffset < characters.length) { currentOffset = nextOffset; renderPage(); } }); // 每页条数选择事件 rowsSelector.addEventListener("change", () => { itemsPerPage = rowsSelector.value; currentOffset = 0; // 切换条数后回到第一页 renderPage(); }); // 初始化加载数据 fetchHeroes();
关键逻辑说明
- 全局状态管理:用全局变量统一管理数据、当前偏移量、每页条数,避免作用域冲突
- 异步数据加载:使用
async/await确保数据加载完成后再渲染,添加错误处理提升健壮性 - 分页渲染优化:
- 动态计算当前页的起始/结束索引,确保不超出数据范围
- 选择"All"时直接渲染所有数据,并禁用分页按钮
- 自动更新按钮禁用状态,第一页禁用上一页,最后一页禁用下一页
- 用户交互优化:切换每页条数时自动回到第一页,保证体验一致性
- 数据容错处理:对可能为空的字段添加
N/A默认值,避免页面显示异常
内容的提问来源于stack exchange,提问作者Hyou
相关产品推荐
相关产品推荐

