在前端开发中,分页功能是处理大量数据展示时的常见需求,为了提升开发效率,我基于原生JavaScript编写了一个轻量级、可复用的分页组件,这个组件设计简洁,易于扩展,能够满足大多数场景下的分页需求,下面将详细介绍这个组件的实现思路、核心代码及使用方法。

组件设计思路
分页组件的核心功能是根据当前页码和每页数据量,动态生成分页导航并处理数据展示逻辑,在设计时,我主要考虑了以下几点:
- 数据驱动:组件通过接收总数据量、每页显示条数等参数,自动计算总页数并渲染分页按钮。
- 事件解耦:通过回调函数将页码变化事件传递给父组件,便于与数据请求逻辑解耦。
- 样式可控:提供基础的CSS类名,方便开发者根据项目需求自定义样式。
- 状态管理:支持禁用状态、当前页高亮等交互逻辑,提升用户体验。
核心代码实现
组件的核心代码包含HTML结构、JavaScript逻辑和基础样式三部分,以下是关键实现细节:
HTML结构
组件的DOM结构采用语义化标签,包含页码导航、上下页按钮和页码跳转功能:
<nav class="pagination" role="pagination">
<button class="pagination-btn pagination-prev" disabled>上一页</button>
<div class="pagination-numbers"></div>
<button class="pagination-btn pagination-next">下一页</button>
<div class="pagination-jump">
<span>跳至</span>
<input type="number" class="pagination-input" min="1" />
<span>页</span>
</div>
</nav>
JavaScript逻辑
使用ES6类语法封装组件功能,核心方法包括:

class Pagination {
constructor(options) {
this.totalItems = options.totalItems || 0;
this.itemsPerPage = options.itemsPerPage || 10;
this.currentPage = options.currentPage || 1;
this.maxVisiblePages = options.maxVisiblePages || 5;
this.container = options.container;
this.onChange = options.onChange || (() => {});
this.init();
}
init() {
this.totalPages = Math.ceil(this.totalItems / this.itemsPerPage);
this.render();
this.bindEvents();
}
render() {
// 渲染页码按钮
const numbersContainer = this.container.querySelector('.pagination-numbers');
numbersContainer.innerHTML = '';
let startPage = Math.max(1, this.currentPage - Math.floor(this.maxVisiblePages / 2));
let endPage = Math.min(this.totalPages, startPage + this.maxVisiblePages - 1);
if (endPage - startPage < this.maxVisiblePages - 1) {
startPage = Math.max(1, endPage - this.maxVisiblePages + 1);
}
for (let i = startPage; i <= endPage; i++) {
const pageBtn = document.createElement('button');
pageBtn.className = `pagination-btn ${i === this.currentPage ? 'active' : ''}`;
pageBtn.textContent = i;
numbersContainer.appendChild(pageBtn);
}
// 更新上下页按钮状态
this.container.querySelector('.pagination-prev').disabled = this.currentPage === 1;
this.container.querySelector('.pagination-next').disabled = this.currentPage === this.totalPages;
}
bindEvents() {
// 上一页/下一页事件
this.container.querySelector('.pagination-prev').addEventListener('click', () => {
if (this.currentPage > 1) {
this.goToPage(this.currentPage - 1);
}
});
this.container.querySelector('.pagination-next').addEventListener('click', () => {
if (this.currentPage < this.totalPages) {
this.goToPage(this.currentPage + 1);
}
});
// 页码点击事件
this.container.addEventListener('click', (e) => {
if (e.target.classList.contains('pagination-numbers')) {
const page = parseInt(e.target.textContent);
this.goToPage(page);
}
});
// 跳转页码事件
const jumpInput = this.container.querySelector('.pagination-input');
jumpInput.addEventListener('change', () => {
const page = parseInt(jumpInput.value);
if (page >= 1 && page <= this.totalPages) {
this.goToPage(page);
} else {
jumpInput.value = this.currentPage;
}
});
}
goToPage(page) {
this.currentPage = page;
this.render();
this.onChange(page);
}
update(totalItems) {
this.totalItems = totalItems;
this.totalPages = Math.ceil(totalItems / this.itemsPerPage);
this.currentPage = Math.min(this.currentPage, this.totalPages);
this.render();
}
}
基础样式
提供简洁的默认样式,确保组件在不同设备上正常显示:
.pagination {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin: 20px 0;
}
.pagination-btn {
padding: 6px 12px;
border: 1px solid #ddd;
background: #fff;
cursor: pointer;
border-radius: 4px;
transition: all 0.3s;
}
.pagination-btn:hover:not(:disabled) {
background: #f0f0f0;
}
.pagination-btn.active {
background: #1890ff;
color: #fff;
border-color: #1890ff;
}
.pagination-btn:disabled {
cursor: not-allowed;
opacity: 0.5;
}
.pagination-numbers {
display: flex;
gap: 4px;
}
.pagination-jump {
display: flex;
align-items: center;
gap: 4px;
}
.pagination-input {
width: 50px;
padding: 6px;
border: 1px solid #ddd;
border-radius: 4px;
text-align: center;
}
使用方法
使用该组件只需三步:
- 创建容器元素并设置类名
- 实例化Pagination类并传入配置参数
- 在回调函数中处理数据请求逻辑
示例代码:
// 1. 创建容器
const paginationContainer = document.createElement('nav');
paginationContainer.className = 'pagination';
document.body.appendChild(paginationContainer);
// 2. 初始化组件
const pagination = new Pagination({
container: paginationContainer,
totalItems: 100, // 总数据量
itemsPerPage: 10, // 每页显示条数
currentPage: 1, // 当前页码
onChange: (page) => {
// 3. 处理数据请求
fetchData(page);
}
});
// 模拟数据请求
function fetchData(page) {
console.log(`正在获取第${page}页数据...`);
// 这里可以添加AJAX请求逻辑
}
扩展建议
虽然这个组件已经满足基本需求,但在实际项目中还可以根据需要进行扩展:

- 支持更多样式主题:通过参数切换不同的UI风格
- 添加加载状态:在数据请求时显示loading动画
- 支持自定义按钮文本:如修改”上一页/下一页”为”‹/›”
- 添加页码范围显示:如显示”第1-10条,共100条”
这个组件的设计遵循了关注点分离原则,将分页逻辑与业务逻辑解耦,同时保持了足够的灵活性,通过简单的配置即可快速集成到项目中,有效减少重复开发工作,对于需要更复杂功能的场景,也可以基于此组件进行二次开发,实现定制化的分页解决方案。



















