TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码

原生JavaScript实现高效分页功能的完整方案

2025-09-02
/
0 评论
/
2 阅读
/
正在检测是否收录...
09/02

原生JavaScript实现高效分页功能的完整方案

一、分页功能的核心需求分析

在Web开发中,分页功能是处理大量数据展示的必备解决方案。一个优秀的分页组件需要满足以下核心需求:

  1. 数据切片处理:将大数据集按指定条数分割
  2. 页码逻辑计算:处理首页、末页、上一页、下一页等边界情况
  3. DOM高效渲染:避免全量重新渲染造成的性能损耗
  4. 用户交互友好:提供直观的导航体验
  5. 响应式设计:适配不同屏幕尺寸的显示方式

二、基础分页实现方案

2.1 HTML结构搭建

html

2.2 JavaScript核心逻辑

javascript
class Pagination {
constructor(options) {
this.totalItems = options.totalItems || 0;
this.currentPage = options.currentPage || 1;
this.pageSize = options.pageSize || 10;
this.maxPages = options.maxPages || 5;
this.container = document.querySelector(options.container);

this.init();

}

init() {
this.render();
this.bindEvents();
}

get totalPages() {
return Math.ceil(this.totalItems / this.pageSize);
}

render() {
if (this.totalPages <= 1) return;

let html = '';
const { startPage, endPage } = this.calculatePaginationRange();

// 上一页按钮
html += `
  <li class="page-item prev ${this.currentPage === 1 ? 'disabled' : ''}">
    <a class="page-link" href="#" data-page="${this.currentPage - 1}">上一页</a>
  </li>`;

// 页码按钮
for (let i = startPage; i <= endPage; i++) {
  html += `
    <li class="page-item ${i === this.currentPage ? 'active' : ''}">
      <a class="page-link" href="#" data-page="${i}">${i}</a>
    </li>`;
}

// 下一页按钮
html += `
  <li class="page-item next ${this.currentPage === this.totalPages ? 'disabled' : ''}">
    <a class="page-link" href="#" data-page="${this.currentPage + 1}">下一页</a>
  </li>`;

this.container.innerHTML = html;

}

calculatePaginationRange() {
let startPage, endPage;

if (this.totalPages <= this.maxPages) {
  startPage = 1;
  endPage = this.totalPages;
} else {
  const maxPagesBeforeCurrent = Math.floor(this.maxPages / 2);
  const maxPagesAfterCurrent = Math.ceil(this.maxPages / 2) - 1;

  if (this.currentPage <= maxPagesBeforeCurrent) {
    startPage = 1;
    endPage = this.maxPages;
  } else if (this.currentPage + maxPagesAfterCurrent >= this.totalPages) {
    startPage = this.totalPages - this.maxPages + 1;
    endPage = this.totalPages;
  } else {
    startPage = this.currentPage - maxPagesBeforeCurrent;
    endPage = this.currentPage + maxPagesAfterCurrent;
  }
}

return { startPage, endPage };

}

bindEvents() {
this.container.addEventListener('click', (e) => {
e.preventDefault();

  const target = e.target.closest('.page-link');
  if (!target) return;

  const newPage = parseInt(target.dataset.page);
  if (newPage && newPage !== this.currentPage && newPage > 0 && newPage <= this.totalPages) {
    this.currentPage = newPage;
    this.render();
    this.onPageChange();
  }
});

}

onPageChange() {
// 触发自定义事件或回调
const event = new CustomEvent('pageChange', {
detail: {
currentPage: this.currentPage,
pageSize: this.pageSize
}
});
document.dispatchEvent(event);
}
}

三、高级功能扩展

3.1 动态数据加载

javascript
// 使用时
const pagination = new Pagination({
container: '#pagination',
totalItems: 150,
currentPage: 1,
pageSize: 10,
maxPages: 5
});

document.addEventListener('pageChange', (e) => {
const { currentPage, pageSize } = e.detail;
loadData(currentPage, pageSize);
});

async function loadData(page, size) {
const response = await fetch(/api/data?page=${page}&size=${size});
const data = await response.json();
renderData(data.items);
pagination.totalItems = data.totalCount;
pagination.render();
}

3.2 移动端适配优化

javascript
// 在render方法中添加移动端判断
render() {
const isMobile = window.innerWidth < 768;

if (isMobile) {
this.maxPages = 3;
} else {
this.maxPages = 5;
}

// 剩余渲染逻辑不变
}

3.3 添加页面跳转输入框

html

javascript // 添加跳转逻辑 document.getElementById('goBtn').addEventListener('click', () => { const pageNum = parseInt(document.getElementById('pageInput').value); if (pageNum && pageNum !== this.currentPage && pageNum > 0 && pageNum <= this.totalPages) { this.currentPage = pageNum; this.render(); this.onPageChange(); } });

四、性能优化建议

  1. 事件委托:使用单个事件监听器处理所有分页按钮点击
  2. 节流处理:对窗口resize事件进行节流控制
  3. 虚拟DOM:对大数据量考虑使用虚拟DOM技术
  4. 缓存机制:对已加载的页面数据进行缓存
  5. 请求取消:在发起新请求时取消未完成的旧请求

五、实际应用示例

javascript
// 完整示例
document.addEventListener('DOMContentLoaded', () => {
// 初始化分页
const pagination = new Pagination({
container: '#pagination',
totalItems: 0, // 初始为0,等待数据加载后更新
currentPage: 1,
pageSize: 10,
maxPages: 5
});

// 首次加载数据
loadData(1, 10);

async function loadData(page, size) {
try {
showLoading();
const response = await fetch(/api/news?page=${page}&size=${size});
const data = await response.json();

  renderNews(data.items);
  pagination.totalItems = data.totalCount;
  pagination.render();
} catch (error) {
  console.error('数据加载失败:', error);
} finally {
  hideLoading();
}

}

function renderNews(items) {
const container = document.getElementById('news-container');
container.innerHTML = items.map(item => <div class="news-item"> <h3>${item.title}</h3> <p>${item.summary}</p> <time>${formatDate(item.publishTime)}</time> </div>).join('');
}
});

六、常见问题解决方案

  1. 页码过多显示混乱



    • 实现页码截断逻辑,显示部分页码加省略号
    • 使用calculatePaginationRange方法控制显示范围
  2. 最后一页数据不足



    • 在数据请求时处理pageSize参数
    • 后端应返回正确的totalCount值
  3. 并发请求导致数据错乱



    • 使用AbortController取消未完成的请求
    • 添加请求序列号校验
  4. 页面跳转后保持滚动位置



    • 使用sessionStorage记录滚动位置
    • 数据加载完成后恢复位置

通过以上方案,我们可以构建出功能完善、性能优异的分页组件,满足大多数Web应用的需求。实际开发中可根据具体业务需求进行适当调整和扩展。

朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/37467/(转载时请注明本文出处及文章链接)

评论 (0)

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月

最新回复

  1. 强强强
    2025-04-07
  2. jesse
    2025-01-16
  3. sowxkkxwwk
    2024-11-20
  4. zpzscldkea
    2024-11-20
  5. bruvoaaiju
    2024-11-14

标签云