Pagination 分页
分页组件,用于数据的分页展示。
基础用法
html
<div id="demo-pagination"></div>
<script>
const pagination = new SaPagination('#demo-pagination', {
total: 100,
pageSize: 10,
current: 1,
onChange: (page, pageSize) => {
console.log('当前页:', page, '每页条数:', pageSize);
}
});
</script>加载 SanoUI 组件中...
完整布局
显示所有分页元素:总数、上一页、页码、下一页、跳转等。
html
<div id="demo-pagination-full"></div>
<script>
const pagination = new SaPagination('#demo-pagination-full', {
total: 100,
pageSize: 10,
current: 1,
layout: 'total, prev, pager, next, jumper',
onChange: (page, pageSize) => {
console.log('页码变化:', page, pageSize);
}
});
</script>加载 SanoUI 组件中...
简单布局
只显示上一页、下一页按钮。
html
<div id="demo-pagination-simple"></div>
<script>
const pagination = new SaPagination('#demo-pagination-simple', {
total: 100,
pageSize: 10,
current: 1,
layout: 'prev, next',
onChange: (page, pageSize) => {
console.log('页码变化:', page, pageSize);
}
});
</script>加载 SanoUI 组件中...
不同尺寸
通过 size 属性设置分页大小。
html
<!-- 大尺寸 -->
<div id="demo-pagination-large"></div>
<script>
new SaPagination('#demo-pagination-large', {
total: 100,
pageSize: 10,
size: 'large'
});
</script>
<!-- 默认尺寸 -->
<div id="demo-pagination-default"></div>
<script>
new SaPagination('#demo-pagination-default', {
total: 100,
pageSize: 10
});
</script>
<!-- 小尺寸 -->
<div id="demo-pagination-small"></div>
<script>
new SaPagination('#demo-pagination-small', {
total: 100,
pageSize: 10,
size: 'small'
});
</script>加载 SanoUI 组件中...
API
构造函数参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| container | 容器选择器或元素 | string | HTMLElement | - |
| options | 配置选项 | SaPaginationOptions | {} |
配置选项
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| total | 总记录数 | number | - | 0 |
| pageSize | 每页条数 | number | - | 10 |
| currentPage | 当前页码 | number | - | 1 |
| layout | 布局 | string | 'total, prev, pager, next, jumper, sizes' | 'prev, pager, next' |
| size | 尺寸 | string | large / default / small | default |
| pageSizes | 每页条数选项 | Array<number> | - | [10, 20, 50, 100] |
| pagerCount | 页码按钮数量(当总页数超过该值时会折叠) | number | - | 7 |
| small | 是否小尺寸 | boolean | - | false |
| disabled | 是否禁用 | boolean | - | false |
| hideOnSinglePage | 只有一页时是否隐藏 | boolean | - | false |
| onChange | 页码变化回调 | function(page, pageSize): void | - | null |
| onPageSizeChange | 每页条数变化回调 | function(pageSize): void | - | null |
方法
| 方法名 | 说明 | 参数 | 返回值 |
|---|---|---|---|
| setCurrentPage(page) | 设置当前页码 | page: number | void |
| setPageSize(pageSize) | 设置每页条数 | pageSize: number | void |
| setTotal(total) | 设置总记录数 | total: number | void |
| getCurrentPage() | 获取当前页码 | - | number |
| getPageSize() | 获取每页条数 | - | number |
| getTotal() | 获取总记录数 | - | number |
| destroy | 销毁实例 | - | void |
自动初始化属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
class="sa-pagination" | 启用自动初始化 | - | - |
data-pagination | 启用自动初始化标记 | boolean | - |
data-total | 总记录数 | number | 0 |
data-page-size | 每页条数 | number | 10 |
data-current | 当前页码 | number | 1 |
data-layout | 布局 | string | 'prev, pager, next' |
data-size | 尺寸 | string | default |
实际使用场景
场景 1:配合表格使用
分页组件与表格组件配合,实现数据分页展示。
html
<div id="pagination-table" style="height: 300px; margin-bottom: 1rem;"></div>
<div id="pagination-control" style="display: flex; justify-content: center;"></div>
<script>
// 模拟数据
const allData = Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
name: `用户 ${i + 1}`,
email: `user${i + 1}@example.com`
}));
let currentPage = 1;
const pageSize = 10;
const table = new SaTable('#pagination-table', {
columns: [
{ field: 'id', label: 'ID', width: 80 },
{ field: 'name', label: '姓名', width: 150 },
{ field: 'email', label: '邮箱', width: 200 }
],
data: [],
bordered: true
});
const pagination = new SaPagination('#pagination-control', {
total: allData.length,
pageSize: pageSize,
currentPage: currentPage,
layout: 'total, sizes, prev, pager, next, jumper',
onChange: (page, size) => {
currentPage = page;
loadTableData(page, size);
},
onPageSizeChange: (size) => {
currentPage = 1;
loadTableData(1, size);
}
});
function loadTableData(page, size) {
const start = (page - 1) * size;
const end = start + size;
const pageData = allData.slice(start, end);
table.updateData(pageData, allData.length);
}
// 初始加载
loadTableData(currentPage, pageSize);
</script>加载 SanoUI 组件中...
场景 2:服务端分页
配合服务端 API 实现真正的服务端分页。
html
<div id="server-pagination-table" style="height: 300px; margin-bottom: 1rem;"></div>
<div id="server-pagination-control" style="display: flex; justify-content: center;"></div>
<script>
let currentPage = 1;
let currentPageSize = 10;
let totalRecords = 0;
const table = new SaTable('#server-pagination-table', {
columns: [
{ field: 'id', label: 'ID', width: 80 },
{ field: 'title', label: '标题', width: 200 },
{ field: 'author', label: '作者', width: 120 },
{ field: 'createTime', label: '创建时间', width: 180 }
],
data: [],
bordered: true
});
const pagination = new SaPagination('#server-pagination-control', {
total: 0,
pageSize: currentPageSize,
currentPage: currentPage,
layout: 'total, sizes, prev, pager, next, jumper',
onChange: async (page, size) => {
currentPage = page;
currentPageSize = size;
await loadData(page, size);
},
onPageSizeChange: async (size) => {
currentPage = 1;
currentPageSize = size;
await loadData(1, size);
}
});
// 模拟服务端 API 调用
async function loadData(page, size) {
try {
// 显示加载状态
table._setState({ loading: true });
// 模拟 API 调用延迟
await new Promise(resolve => setTimeout(resolve, 500));
// 模拟服务端返回的数据
const mockData = Array.from({ length: 200 }, (_, i) => ({
id: i + 1,
title: `文章标题 ${i + 1}`,
author: `作者 ${(i % 5) + 1}`,
createTime: `2024-01-${String((i % 28) + 1).padStart(2, '0')} 10:00:00`
}));
totalRecords = mockData.length;
const start = (page - 1) * size;
const end = start + size;
const pageData = mockData.slice(start, end);
// 更新表格和分页
table.updateData(pageData, totalRecords);
pagination.setTotal(totalRecords);
pagination.setCurrentPage(page);
table._setState({ loading: false });
} catch (error) {
console.error('加载数据失败:', error);
table._setState({ loading: false });
}
}
// 初始加载
loadData(currentPage, currentPageSize);
</script>加载 SanoUI 组件中...
场景 3:动态更新总数
根据筛选条件动态更新分页的总数。
html
<div style="margin-bottom: 1rem;">
<select id="status-filter" onchange="applyFilter()" style="padding: 0.5rem; border: 1px solid #ddd; border-radius: 4px;">
<option value="">全部状态</option>
<option value="active">正常</option>
<option value="inactive">禁用</option>
</select>
</div>
<div id="filter-table" style="height: 300px; margin-bottom: 1rem;"></div>
<div id="filter-pagination" style="display: flex; justify-content: center;"></div>
<script>
// 所有数据
const allData = [
...Array.from({ length: 50 }, (_, i) => ({ id: i + 1, name: `用户 ${i + 1}`, status: 'active' })),
...Array.from({ length: 30 }, (_, i) => ({ id: 51 + i, name: `用户 ${51 + i}`, status: 'inactive' }))
];
let filteredData = allData;
let currentPage = 1;
const pageSize = 10;
const table = new SaTable('#filter-table', {
columns: [
{ field: 'id', label: 'ID', width: 80 },
{ field: 'name', label: '姓名', width: 150 },
{ field: 'status', label: '状态', width: 100 }
],
data: [],
bordered: true
});
const pagination = new SaPagination('#filter-pagination', {
total: filteredData.length,
pageSize: pageSize,
currentPage: currentPage,
layout: 'total, prev, pager, next',
onChange: (page) => {
currentPage = page;
loadPageData();
}
});
function applyFilter() {
const status = document.getElementById('status-filter').value;
if (status) {
filteredData = allData.filter(item => item.status === status);
} else {
filteredData = allData;
}
// 重置到第一页并更新总数
currentPage = 1;
pagination.setTotal(filteredData.length);
pagination.setCurrentPage(1);
loadPageData();
}
function loadPageData() {
const start = (currentPage - 1) * pageSize;
const end = start + pageSize;
const pageData = filteredData.slice(start, end);
table.updateData(pageData, filteredData.length);
}
// 初始加载
loadPageData();
</script>加载 SanoUI 组件中...
场景 4:简单分页导航
只显示上一页和下一页按钮的简单分页。
html
<div id="simple-pagination" style="display: flex; justify-content: center;"></div>
<script>
const simplePagination = new SaPagination('#simple-pagination', {
total: 100,
pageSize: 10,
currentPage: 1,
layout: 'prev, next',
onChange: (page) => {
console.log('跳转到第', page, '页');
// 这里可以加载对应页的数据
}
});
</script>加载 SanoUI 组件中...
场景 5:禁用状态
在加载数据时禁用分页组件,防止重复操作。
html
<div id="disabled-pagination" style="display: flex; justify-content: center; margin-bottom: 1rem;"></div>
<button class="sa-button sa-button--primary" onclick="toggleLoading()">切换加载状态</button>
<script>
const pagination = new SaPagination('#disabled-pagination', {
total: 100,
pageSize: 10,
currentPage: 1,
layout: 'total, prev, pager, next, jumper',
disabled: false,
onChange: (page) => {
console.log('页码变化:', page);
}
});
let isLoading = false;
function toggleLoading() {
isLoading = !isLoading;
pagination.config.disabled = isLoading;
pagination._render();
if (isLoading) {
console.log('分页已禁用');
} else {
console.log('分页已启用');
}
}
</script>加载 SanoUI 组件中...
注意事项
- 页码计算:总页数 = Math.ceil(total / pageSize)
- 布局配置:
layout可以包含total, sizes, prev, pager, next, jumper的组合 - 单页隐藏:设置
hideOnSinglePage: true时,只有一页数据会自动隐藏分页组件 - 页码按钮数量:通过
pagerCount控制显示的页码按钮数量,超出时会折叠 - 事件回调:
onChange在页码或每页条数变化时都会触发
常见问题
Q: 如何获取当前页码和每页条数?
A: 使用 getCurrentPage() 和 getPageSize() 方法:
javascript
const currentPage = pagination.getCurrentPage();
const pageSize = pagination.getPageSize();Q: 如何动态更新总数?
A: 使用 setTotal() 方法:
javascript
pagination.setTotal(newTotal);Q: 如何跳转到指定页?
A: 使用 setCurrentPage() 方法:
javascript
pagination.setCurrentPage(5); // 跳转到第 5 页Q: 如何自定义每页条数选项?
A: 通过 pageSizes 配置:
javascript
const pagination = new SaPagination('#pagination', {
pageSizes: [5, 10, 20, 50, 100]
});Q: 如何实现服务端分页?
A: 在 onChange 回调中调用 API:
javascript
const pagination = new SaPagination('#pagination', {
onChange: async (page, pageSize) => {
const response = await fetch(`/api/data?page=${page}&pageSize=${pageSize}`);
const result = await response.json();
// 更新表格数据
table.updateData(result.data, result.total);
// 更新分页总数
pagination.setTotal(result.total);
}
});Q: 如何隐藏单页时的分页组件?
A: 设置 hideOnSinglePage: true:
javascript
const pagination = new SaPagination('#pagination', {
hideOnSinglePage: true
});