1、用法
在使vue或者react中,经常会用到table组件,它实现了一些功能封装。
一般我们只要传入行数据和列数据,即可实现页面渲染,下面我们讨论一下基本思想。
- 勾选列、排序、展开折叠行
- 固定某些列
- 多级表头,搜索过滤
- 表尾合计行
import { Space, Table, Tag } from 'antd';
import React from 'react';
const columns = [
{ title: 'Name', dataIndex: 'name', key: 'name', render: (text) => <a>{text}</a>, },
{ title: 'Age', dataIndex: 'age', key: 'age', },
{ title: 'Address', dataIndex: 'address', key: 'address', },
{ title: 'Tags', key: 'tags', dataIndex: 'tags', render: (_, { tags }) =>(
<> { tags.map((tag) => {
let color = tag.length > 5 ? 'geekblue' : 'green';
if (tag === 'loser') {
color = 'volcano';
}
return ( <Tag color={color} key={tag}> {tag.toUpperCase()} </Tag> )
})
}</> ),
},
{ title: 'Action', key: 'action', render: (_, record) => (
<Space size="middle"> <a>Invite {record.name}</a> <a>Delete</a> </Space> ),
},
];
const data = [
{ key: '1', name: 'John Brown', age: 32, address: 'New York No. 1 Lake Park', tags: ['nice', 'developer'], },
{ key: '2', name: 'Jim Green', age: 42, address: 'London No. 1 Lake Park', tags: ['loser'], },
{ key: '3', name: 'Joe Black', age: 32, address: 'Sidney No. 1 Lake Park', tags: ['cool', 'teacher'], },
];
const App = () => <Table columns={columns} dataSource={data} />;
export default App;
2、实现分析
如react-element,table目录下主要有如下文件
2.1 TableStore
最外层为TableStore组件,它主要是
- 存储公共数据状态,如 columns、fixedColumns、data、currentRow、selectedRows、sortOrder等,并通过getChildContext共享给子组件;
- 暴露的method,如toggleRowSelection 、toggeleRowExpanded等,并通过dispatchEvent方法来触发给外层组件
- updataData和updataColumns等方法更新公共数据
- render TableLayout组件
2.2 TableLayout
主要负责页面布局时的数据计算
- 维护布局数据,如 表宽度、表头表体表尾高度、横向纵向滚动距离 等,并通过getChildContext共享给子组件;
- 生命周期执行scheduleLayout函数计算布局数据
scheduleLayout()=>{
this.setState(this.caculateWidth(),()=>{
this.updateHeight()
this.updataScrollY()
}
}
- render Table组件
2.3 Table
- 分为三个table、左固定fixedColumns、正常table、右固定rightFixedColumns,其中左固定和右固定是TableStore中计算的,如果有这两部分则绘制;
- 每个table分为三部分,TableHeader、TableBody、TableFooter,其中多级表头、搜索过滤、点击排序等在TableHeader中实现、表尾合计在TableFooter中实现;
- 三个table布局数据进一步处理
- syncScroll实现同步滚动,横向滚动时表尾表头scrollLeft同步改变,纵向滚动时左右固定表格scrollTop同步改变
2.4 TableBody
- 渲染元素table组件,遍历data数组绘制tr节点,遍历columns数组绘制td节点;
- 通过 colgroup和col标签控制表宽度;
- tr和td确定一个cell单元格,执行column.render绘制单元格
- 行和列点击会触发事件
3、拖动表格改变宽度
- 使用react element组件自带该功能,在TableHeader组件中th列标签会监听onMouseMove、onMouseDown事件,进而重新计算列宽。
- 使用react antd组件,表格缺少该功能,需要自己实现。
实现方式为自定义 components.header.cell 即表头的列单元,给之包裹Reactable标签,监听onResize事件,重新计算columns数据里的width属性。
const ResizableTitle = (props: any) => {
const {onResize, width, ...restProps} = props
if (!width) {
return <th {...restProps} />
}
return (
<Resizable
width={width}
height={0}
onResize={onResize}
draggableOpts={{enableUserSelectHack: false}}
>
<th {...restProps} />
</Resizable>
)
}
欢迎关注我的前端自检清单,我和你一起成长