如何构建一个自定义Table
在刚上手项目的时候,通常会碰到一些自定义组件的问题,一般的组件自定义其实都相对比较简单,根据自己的功能完全用div手撸一个组件出来都可以,但是面对自定义Table的时候,因为table属性的特殊性还有相关内容的复杂程度,自定义table就存在一定的难度了,下面我会开始介绍,如何从零开始构建一个table组件。
分析组件的构成
想要构建一个组件,我的观点是尽可能的做到以下的几点:
- 解耦合:解耦合,简单的说就是组件内部尽量不要存在和组件外部高耦合的内容(例如在组件内部进行接口请求),尽可能的保证组件的独立性,它就是一个UI容器,接受特定格式的数据就可以渲染出你想要的UI。
- 简洁性:单个组件不要过于复杂,如果有必要的话,拆分成多个子组件,使得组件的可读性和使用更加的清晰明了,如果实在无法做到简洁,就把注释写的完整一点
- 完整性:封装的组件,功能性肯定要保证尽可能的完整,比如我们将要说明的自定义table,它可能需要有的排序功能,固定表头之类的,最好就是在构建组件的时候都考虑清楚,不然到了后期想要加功能会复杂很多。
- 冗余量:给组件提供一些可以外部自定义的方法,增加组件本身的变体的可能性。
上面的内容就是我分析组件的构成的主要方法了,下面以我们将要自定义的table为例,分为以下几个步骤:
明确功能
我们的table需要实现的目标是
- 分离模式的UI
- 单个表格元素的基础样式配置
- 圆角的表头和每一行,可能存在的自定义行颜色
- 表头或表内容的文本对其方式(居左,居中,居右),垂直对齐方式。。
- 可能存在的固定表头
- 可能存在的固定某几列
- 可能存在的嵌套表格
- 表格内容排序
- 可能存在的表头是多层级的
...
html、css实现
上面我们已经确定了基本的功能,接着我们在组件化之前,就要开始尝试通过纯html和css的方法先构建一个简单的符合上面功能的模版出来,或者说是一个写死的组件。比如下图的这种简单样式
想要复刻上面的样式,简单的代码如下:
import './index.less'
import React from 'react'
const NewTable = () => {
return <div className='w-screen'>
New Table
<div className='flex w-full justify-center items-center'>
<table className='custom_new_table'>
<thead>
<tr>
<th className='custom_th' colSpan={1} rowSpan={1}>table Th 1</th>
<th className='custom_th' colSpan={1} rowSpan={1}>table Th 2</th>
<th className='custom_th' colSpan={1} rowSpan={1}>table Th 3</th>
<th className='custom_th' colSpan={1} rowSpan={1}>table Th 4</th>
<th className='custom_th' colSpan={1} rowSpan={1}>table Th 5</th>
</tr>
</thead>
<tbody>
<tr>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 1</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 2</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 3</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 4</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 5</td>
</tr>
<tr>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 1</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 2</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 3</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 4</td>
<td className='custom_td' colSpan={1} rowSpan={1}>table Td 5</td>
</tr>
</tbody>
</table>
</div>
</div>
}
export default NewTable
.custom_new_table {
width: 100%;
// background: #d6d6d6;
border-collapse: separate;
border-spacing: 0px 15px;
thead {
.custom_th {
background-color: aqua;
padding: 12px 16px;
}
.custom_th:first-child {
border-bottom-left-radius: 15px;
border-top-left-radius: 15px;
}
.custom_th:last-child {
border-bottom-right-radius: 15px;
border-top-right-radius: 15px;
}
}
tbody {
.custom_td {
background-color: aquamarine;
padding: 12px 16px;
}
.custom_td:first-child {
border-bottom-left-radius: 15px;
border-top-left-radius: 15px;
}
.custom_td:last-child {
border-bottom-right-radius: 15px;
border-top-right-radius: 15px;
}
}
}
分析组件
当你完成了能够实现所有想要功能的写死的html模版后,对模版和css进行分析,拆解。比较简单的拆分就是:
- 能够遍历的--外面传入一个items,在组件内部使用map遍历
- 需要外部控制的--外面传入一个参数,在组建内部根据参数值的不同设置不同的UI或者方法
- 内部主动向外抛出的--外部传入一个函数,在组建内部调用函数并且传值出去
- 部分内容可以外部自定义的--外部传入一个组件或者一个函数,根据类型不同,进行渲染
- 外部控制调用内部方法的--外部使用ref,内部接受ref,并构建相应的函数方法
开始构建组件
上面已经对组件进行了分析,并且写了一个完全死的模版,现在这一步就是根据分析组件的结果,对组件进行构建了。
(具体的内容和代码未完成。。。)
测试组件
这一步就是创建各种数据类型,测试组件是否能够达到预期的渲染效果
编写注释
这一步很重要,因为你会发现过了2个月,你可能自己看自己的组件都是一脸懵逼,写注释有助于快速定位问题以及后续扩展组件功能(这里建议JSDoc格式编写)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。