386 lines
8.5 KiB
Markdown
386 lines
8.5 KiB
Markdown
# ListTable 组件
|
||
|
||
## 组件说明
|
||
|
||
列表表格组件,基于 Ant Design Table 组件封装,提供统一的表格样式、行选择、分页、滚动和行点击等功能。
|
||
|
||
## 组件位置
|
||
|
||
```
|
||
src/components/ListTable/ListTable.jsx
|
||
src/components/ListTable/ListTable.css
|
||
```
|
||
|
||
## 参数说明
|
||
|
||
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| columns | Array<ColumnConfig> | 是 | - | 表格列配置数组 |
|
||
| dataSource | Array<Object> | 是 | - | 表格数据源 |
|
||
| rowKey | string | 否 | 'id' | 行数据的唯一标识字段名 |
|
||
| selectedRowKeys | Array<string\|number> | 否 | [] | 选中行的 key 数组 |
|
||
| onSelectionChange | function(keys: Array) | 否 | - | 行选择变化回调 |
|
||
| pagination | Object\|false | 否 | 默认配置 | 分页配置,false 表示不分页 |
|
||
| scroll | Object | 否 | { x: 1200 } | 表格滚动配置 |
|
||
| onRowClick | function(record: Object) | 否 | - | 行点击回调 |
|
||
| selectedRow | Object | 否 | - | 当前选中的行数据对象 |
|
||
| loading | boolean | 否 | false | 表格加载状态 |
|
||
| className | string | 否 | '' | 自定义类名 |
|
||
|
||
### ColumnConfig 列配置
|
||
|
||
继承自 Ant Design Table 的列配置,常用属性:
|
||
|
||
| 属性名 | 类型 | 说明 |
|
||
|--------|------|------|
|
||
| title | string\|ReactNode | 列标题 |
|
||
| dataIndex | string | 数据字段名 |
|
||
| key | string | 列唯一标识 |
|
||
| width | number | 列宽度 |
|
||
| align | 'left'\|'center'\|'right' | 对齐方式 |
|
||
| fixed | 'left'\|'right' | 固定列 |
|
||
| render | function(value, record, index) | 自定义渲染函数 |
|
||
|
||
### 默认分页配置
|
||
|
||
```javascript
|
||
{
|
||
pageSize: 10,
|
||
showSizeChanger: true,
|
||
showQuickJumper: true,
|
||
showTotal: (total) => `共 ${total} 条`,
|
||
}
|
||
```
|
||
|
||
## 使用示例
|
||
|
||
### 基础用法
|
||
|
||
```jsx
|
||
import ListTable from '../components/ListTable/ListTable'
|
||
|
||
function MyPage() {
|
||
const columns = [
|
||
{
|
||
title: '序号',
|
||
dataIndex: 'id',
|
||
key: 'id',
|
||
width: 80,
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '用户名',
|
||
dataIndex: 'userName',
|
||
key: 'userName',
|
||
width: 150,
|
||
},
|
||
{
|
||
title: '姓名',
|
||
dataIndex: 'name',
|
||
key: 'name',
|
||
width: 120,
|
||
},
|
||
{
|
||
title: '状态',
|
||
dataIndex: 'status',
|
||
key: 'status',
|
||
width: 100,
|
||
render: (status) => (
|
||
<Tag color={status === 'enabled' ? 'green' : 'default'}>
|
||
{status === 'enabled' ? '启用' : '停用'}
|
||
</Tag>
|
||
),
|
||
},
|
||
]
|
||
|
||
const dataSource = [
|
||
{ id: 1, userName: 'admin', name: '管理员', status: 'enabled' },
|
||
{ id: 2, userName: 'user', name: '张三', status: 'disabled' },
|
||
]
|
||
|
||
return (
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
/>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 带行选择
|
||
|
||
```jsx
|
||
import { useState } from 'react'
|
||
import ListTable from '../components/ListTable/ListTable'
|
||
|
||
function UserListPage() {
|
||
const [selectedRowKeys, setSelectedRowKeys] = useState([])
|
||
|
||
return (
|
||
<div>
|
||
{/* 显示选中的数量 */}
|
||
<div>已选择 {selectedRowKeys.length} 项</div>
|
||
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
selectedRowKeys={selectedRowKeys}
|
||
onSelectionChange={setSelectedRowKeys}
|
||
/>
|
||
</div>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 带行点击和高亮
|
||
|
||
```jsx
|
||
import { useState } from 'react'
|
||
import ListTable from '../components/ListTable/ListTable'
|
||
|
||
function UserListPage() {
|
||
const [selectedUser, setSelectedUser] = useState(null)
|
||
|
||
const handleRowClick = (record) => {
|
||
setSelectedUser(record)
|
||
// 打开详情抽屉等操作
|
||
setShowDetailDrawer(true)
|
||
}
|
||
|
||
return (
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
onRowClick={handleRowClick}
|
||
selectedRow={selectedUser}
|
||
/>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 自定义分页
|
||
|
||
```jsx
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
pagination={{
|
||
pageSize: 20,
|
||
showSizeChanger: true,
|
||
showQuickJumper: true,
|
||
showTotal: (total) => `总计 ${total} 条记录`,
|
||
pageSizeOptions: ['10', '20', '50', '100'],
|
||
}}
|
||
/>
|
||
```
|
||
|
||
### 禁用分页
|
||
|
||
```jsx
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
pagination={false}
|
||
/>
|
||
```
|
||
|
||
### 带加载状态
|
||
|
||
```jsx
|
||
import { useState, useEffect } from 'react'
|
||
|
||
function UserListPage() {
|
||
const [loading, setLoading] = useState(false)
|
||
const [dataSource, setDataSource] = useState([])
|
||
|
||
const fetchData = async () => {
|
||
setLoading(true)
|
||
try {
|
||
const data = await api.fetchUsers()
|
||
setDataSource(data)
|
||
} finally {
|
||
setLoading(false)
|
||
}
|
||
}
|
||
|
||
useEffect(() => {
|
||
fetchData()
|
||
}, [])
|
||
|
||
return (
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
loading={loading}
|
||
/>
|
||
)
|
||
}
|
||
```
|
||
|
||
### 横向滚动(列较多时)
|
||
|
||
```jsx
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
scroll={{ x: 1600 }} // 内容宽度超过容器时出现横向滚动
|
||
/>
|
||
```
|
||
|
||
### 固定列
|
||
|
||
```jsx
|
||
const columns = [
|
||
{
|
||
title: '序号',
|
||
dataIndex: 'id',
|
||
key: 'id',
|
||
width: 80,
|
||
fixed: 'left', // 固定在左侧
|
||
},
|
||
// ... 其他列
|
||
{
|
||
title: '操作',
|
||
key: 'action',
|
||
width: 200,
|
||
fixed: 'right', // 固定在右侧
|
||
render: (_, record) => (
|
||
<Space>
|
||
<Button type="link" size="small">编辑</Button>
|
||
<Button type="link" size="small" danger>删除</Button>
|
||
</Space>
|
||
),
|
||
},
|
||
]
|
||
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={dataSource}
|
||
scroll={{ x: 1600 }}
|
||
/>
|
||
```
|
||
|
||
### 完整示例
|
||
|
||
```jsx
|
||
import { useState } from 'react'
|
||
import ListTable from '../components/ListTable/ListTable'
|
||
import { Tag, Button, Space } from 'antd'
|
||
import { EditOutlined, DeleteOutlined } from '@ant-design/icons'
|
||
|
||
function UserListPage() {
|
||
const [selectedRowKeys, setSelectedRowKeys] = useState([])
|
||
const [selectedUser, setSelectedUser] = useState(null)
|
||
const [showDetailDrawer, setShowDetailDrawer] = useState(false)
|
||
|
||
const columns = [
|
||
{
|
||
title: '序号',
|
||
dataIndex: 'id',
|
||
key: 'id',
|
||
width: 80,
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '用户名',
|
||
dataIndex: 'userName',
|
||
key: 'userName',
|
||
width: 150,
|
||
},
|
||
{
|
||
title: '姓名',
|
||
dataIndex: 'name',
|
||
key: 'name',
|
||
width: 120,
|
||
},
|
||
{
|
||
title: '用户分组',
|
||
dataIndex: 'group',
|
||
key: 'group',
|
||
width: 150,
|
||
render: (text) => <Tag color="blue">{text}</Tag>,
|
||
},
|
||
{
|
||
title: '状态',
|
||
dataIndex: 'status',
|
||
key: 'status',
|
||
width: 100,
|
||
align: 'center',
|
||
render: (status) => (
|
||
<Tag color={status === 'enabled' ? 'green' : 'default'}>
|
||
{status === 'enabled' ? '启用' : '停用'}
|
||
</Tag>
|
||
),
|
||
},
|
||
{
|
||
title: '操作',
|
||
key: 'action',
|
||
width: 180,
|
||
fixed: 'right',
|
||
render: (_, record) => (
|
||
<Space size="small" onClick={(e) => e.stopPropagation()}>
|
||
<Button
|
||
type="link"
|
||
size="small"
|
||
icon={<EditOutlined />}
|
||
onClick={() => handleEdit(record)}
|
||
>
|
||
编辑
|
||
</Button>
|
||
<Button
|
||
type="link"
|
||
size="small"
|
||
icon={<DeleteOutlined />}
|
||
danger
|
||
onClick={() => handleDelete(record)}
|
||
>
|
||
删除
|
||
</Button>
|
||
</Space>
|
||
),
|
||
},
|
||
]
|
||
|
||
const handleRowClick = (record) => {
|
||
setSelectedUser(record)
|
||
setShowDetailDrawer(true)
|
||
}
|
||
|
||
return (
|
||
<ListTable
|
||
columns={columns}
|
||
dataSource={filteredUsers}
|
||
selectedRowKeys={selectedRowKeys}
|
||
onSelectionChange={setSelectedRowKeys}
|
||
onRowClick={handleRowClick}
|
||
selectedRow={selectedUser}
|
||
scroll={{ x: 1400 }}
|
||
/>
|
||
)
|
||
}
|
||
```
|
||
|
||
## 样式定制
|
||
|
||
组件提供以下 CSS 类名供自定义样式:
|
||
|
||
- `.list-table-container` - 表格容器
|
||
- `.row-selected` - 选中行的类名
|
||
|
||
## 使用场景
|
||
|
||
1. **用户列表** - 显示和管理用户数据
|
||
2. **设备列表** - 显示和管理设备信息
|
||
3. **订单列表** - 显示订单数据
|
||
4. **任何需要表格展示的数据列表**
|
||
|
||
## 注意事项
|
||
|
||
1. `columns` 配置中的 `key` 必须唯一
|
||
2. `dataSource` 中的每条数据必须有 `rowKey` 指定的唯一标识字段(默认为 `id`)
|
||
3. 操作列中的点击事件需要使用 `e.stopPropagation()` 阻止事件冒泡,避免触发行点击
|
||
4. 当列数较多时,建议设置合适的 `scroll.x` 值并固定首尾列
|
||
5. `selectedRow` 用于高亮显示,`selectedRowKeys` 用于多选
|
||
6. 分页的 `total` 值会自动根据 `dataSource.length` 计算
|
||
7. 使用 `render` 函数时,要注意性能,避免在渲染函数中进行复杂计算
|