{
// 如果有选中项,显示选择信息和全选操作
if (selectedRowKeys.length > 0) {
if (isAllPagesSelected) {
return (
已选择全部 {total} 条数据
清除选择
)
} else if (selectedRowKeys.length < total) {
return (
已选择 {selectedRowKeys.length} 条数据
选择全部 {total} 条
清除
)
} else {
return (
已选择全部 {total} 条数据
清除选择
)
}
}
// 无选中项时,显示常规的分页信息
return `共 ${total} 条`
},
onChange: (page, size) => {
setCurrentPage(page)
setPageSize(size)
},
}}
/>
```
#### 分页器样式
```css
/* 分页器中的选择信息样式 */
.pagination-selection-info {
color: rgba(0, 0, 0, 0.85);
font-size: 14px;
}
.pagination-selection-info strong {
color: #1677ff;
font-weight: 600;
margin: 0 4px;
}
.pagination-selection-info a {
color: #1677ff;
cursor: pointer;
text-decoration: none;
transition: all 0.2s;
}
.pagination-selection-info a:hover {
text-decoration: underline;
}
```
## 🚀 完整使用示例
### 状态管理
```jsx
import { useState } from 'react'
function MyListPage() {
// 数据源(实际项目中通常从 API 获取)
const [dataSource] = useState([...]) // 所有数据
const [totalCount] = useState(dataSource.length)
// 分页状态
const [currentPage, setCurrentPage] = useState(1)
const [pageSize, setPageSize] = useState(10)
// 选择状态
const [selectedRowKeys, setSelectedRowKeys] = useState([])
const [isAllPagesSelected, setIsAllPagesSelected] = useState(false)
// 当前页数据
const currentPageData = useMemo(() => {
const start = (currentPage - 1) * pageSize
const end = start + pageSize
return dataSource.slice(start, end)
}, [dataSource, currentPage, pageSize])
// ... 处理函数
}
```
### 核心处理函数
```jsx
// 选择变化处理(重要:支持跨页选择)
const handleSelectionChange = (keys) => {
// keys 是当前页面操作后的选中项
// 需要合并其他页的选中项,以保持跨页选择状态
const currentPageKeys = currentPageData.map(item => item.id)
const otherPagesSelectedKeys = selectedRowKeys.filter(key => !currentPageKeys.includes(key))
const newSelectedKeys = [...otherPagesSelectedKeys, ...keys]
setSelectedRowKeys(newSelectedKeys)
setIsAllPagesSelected(false)
}
// 选择所有页
const handleSelectAllPages = () => {
setIsAllPagesSelected(true)
setSelectedRowKeys(dataSource.map(item => item.id)) // 设置所有数据的 key
message.success(`已选择全部 ${totalCount} 条数据`)
}
// 清除选择
const handleClearSelection = () => {
setSelectedRowKeys([])
setIsAllPagesSelected(false)
message.info('已清除选择')
}
// 批量删除
const handleBatchDelete = () => {
Modal.confirm({
title: '确认删除',
content: isAllPagesSelected
? `确定要删除全部 ${totalCount} 条数据吗?`
: `确定要删除选中的 ${selectedRowKeys.length} 条数据吗?`,
onOk: () => {
// 执行删除逻辑
if (isAllPagesSelected) {
// 删除所有数据
} else {
// 删除选中的数据:selectedRowKeys
}
handleClearSelection()
},
})
}
```
### 页面结构
```jsx
return (
{/* 操作栏 - 显示选择信息和全选操作 */}
0
? {
count: selectedRowKeys.length,
total: totalCount,
isAllPagesSelected,
}
: null
}
onSelectAllPages={handleSelectAllPages}
onClearSelection={handleClearSelection}
search={...}
/>
{/* 列表表格 - 分页器只显示分页信息 */}
`共 ${total} 条`,
}}
/>
)
```
## 💡 最佳实践
### 0. 跨页选择的实现要点(重要!)
由于 Table 组件只接收当前页数据(`currentPageData`),需要手动维护跨页的选中状态:
```jsx
const handleSelectionChange = (keys) => {
// ❌ 错误做法:直接替换会丢失其他页的选择
// setSelectedRowKeys(keys)
// ✅ 正确做法:合并其他页的选择
const currentPageKeys = currentPageData.map(item => item.id)
const otherPagesSelectedKeys = selectedRowKeys.filter(key => !currentPageKeys.includes(key))
const newSelectedKeys = [...otherPagesSelectedKeys, ...keys]
setSelectedRowKeys(newSelectedKeys)
setIsAllPagesSelected(false)
}
```
**工作原理**:
1. `currentPageKeys` - 当前页所有数据的 key 列表
2. `otherPagesSelectedKeys` - 从已选项中过滤出不在当前页的 keys(即其他页的选择)
3. `newSelectedKeys` - 合并其他页的选择 + 当前页的新选择
4. 这样就保持了所有页的选中状态
### 1. 批量操作提示
执行批量操作时,明确提示操作范围:
```jsx
const handleBatchDelete = () => {
const count = isAllPagesSelected ? totalCount : selectedRowKeys.length
const scope = isAllPagesSelected ? '全部' : '选中的'
Modal.confirm({
title: '确认删除',
content: `确定要删除${scope} ${count} 条数据吗?此操作不可恢复。`,
okText: '确定',
cancelText: '取消',
okButtonProps: { danger: true },
onOk: async () => {
try {
if (isAllPagesSelected) {
await deleteAll()
} else {
await deleteByIds(selectedRowKeys)
}
message.success('删除成功')
handleClearSelection()
refreshData()
} catch (error) {
message.error('删除失败:' + error.message)
}
},
})
}
```
### 2. 分页切换时的选择状态
根据业务需求,可以选择两种策略:
**策略 A:保持选择状态**(推荐)
```jsx
// 切换分页时,保持已选择的数据
const handlePageChange = (page, size) => {
setCurrentPage(page)
setPageSize(size)
// 不清除 selectedRowKeys,保持选择状态
}
```
**策略 B:清除选择状态**
```jsx
// 切换分页时,清除选择
const handlePageChange = (page, size) => {
setCurrentPage(page)
setPageSize(size)
handleClearSelection() // 清除选择
}
```
### 3. 后端 API 对接
跨页全选时,后端 API 应支持两种方式:
```jsx
// 方式1:发送所有选中的 ID(推荐小数据量)
const handleBatchOperation = async () => {
await api.batchOperation({
ids: selectedRowKeys, // 所有选中的 ID
})
}
// 方式2:发送全选标识 + 筛选条件(推荐大数据量)
const handleBatchOperation = async () => {
await api.batchOperation({
selectAll: isAllPagesSelected,
filters: currentFilters, // 当前筛选条件
excludeIds: [], // 排除的 ID(如果有反选功能)
})
}
```
### 4. 性能优化
当数据量很大时(如超过 10000 条),避免一次性加载所有 ID:
```jsx
const handleSelectAllPages = () => {
setIsAllPagesSelected(true)
// 不要: setSelectedRowKeys(dataSource.map(item => item.id))
// 太多 ID 会导致性能问题
// 推荐: 只标记状态,实际操作时由后端根据筛选条件处理
message.success(`已选择全部数据`)
}
const handleBatchDelete = async () => {
if (isAllPagesSelected) {
// 发送全选标识和筛选条件,由后端处理
await api.deleteAll({ filters: currentFilters })
} else {
// 发送具体的 ID 列表
await api.deleteByIds(selectedRowKeys)
}
}
```
## 📝 注意事项
1. **全选状态的一致性**
- 手动勾选/取消勾选时,应取消跨页全选状态
- 确保 `selectedRowKeys` 和 `isAllPagesSelected` 状态同步
2. **筛选和搜索**
- 执行筛选或搜索后,应清除选择状态
- 或者保持选择,但提示用户"选择的数据可能不在当前筛选结果中"
3. **数据刷新**
- 刷新数据后,应重新评估选择状态的有效性
- 建议清除选择,或检查已选数据是否仍然存在
4. **权限控制**
- 批量操作应检查权限
- 跨页全选时,应提示可能操作大量数据
## 🎨 样式定制
### ListActionBar 批量操作区样式定制
```css
/* 修改选中信息区域背景色 */
.selection-info {
background: #f0f9ff;
border-color: #69b1ff;
}
/* 修改选中数量颜色 */
.selection-count strong {
color: #ff4d4f;
}
/* 修改全部页标识颜色 */
.all-pages-tag {
color: #ff4d4f;
}
/* 修改链接颜色 */
.select-all-link,
.clear-selection-link {
color: #52c41a;
}
```
## 🔗 相关组件
- [ListTable](./ListTable.md) - 列表表格组件
- [ListActionBar](./ListActionBar.md) - 列表���作栏组件
- [PageTitleBar](./PageTitleBar.md) - 页面标题栏组件
## 📚 参考资料
- [Ant Design Table 组件](https://ant.design/components/table-cn/)
- [Ant Design Pagination 组件](https://ant.design/components/pagination-cn/)
---
**更新日志**
- v1.2.0 (2025-11-18)
- ♻️ 重构设计:将全选功能集成到操作栏,分页器只显示分页信息
- ✨ 更清晰的职责分离:操作相关在操作栏,分页相关在分页器
- 📝 更新文档和使用示例
- v1.1.0 (2025-11-18)
- ♻️ 重构设计:将全选功能集成到分页器,移除独立的 SelectionAlert 组件
- ✨ 更简洁的交互:选择信息、全选操作、分页控制集中在一个区域
- 📝 更新文档和使用示例
- v1.0.0 (2025-11-18)
- ✨ 新增 SelectionAlert 组件
- ✨ 扩展 ListActionBar 支持批量操作
- ✨ 扩展 ListTable 支持跨页全选状态
- 📝 完善文档和使用示例