• 如何写好一个React table component


    最近上手做一个公司项目,前端用React, 所以为了减少冗余代码,对组件的复用率要求很高,这不需要一个React table component

    为了实现当前的业务需求小编很快写了第一个component

           分析:table分为两个部分header和body,header是固定的,而body的列数固定,但是行数不固定。对于data,也就是table的body,是一个对象数组,每一个对象就是table的一行,对象的属性名称也是固定的。根据上述分析结果,我写了下面这个component。

    1.第一个table component

     先上代码:

    import React from 'react'
    import PropTypes from 'prop-types'
    import { Table } from 'react-bootstrap'
    import { RowHead } from './style'
    
    const TableHeader = props => {
        const { data, headerFormatter } = props
        return (
            <thead>
                <RowHead>
                    {data &&
                        data.map(item => <th key={item}> {headerFormatter ? headerFormatter(item) : item}</th>)}
                </RowHead>
    
            </thead>
        )
    }
    TableHeader.propTypes = {
        data: PropTypes.arrayOf(PropTypes.string).isRequired,
        headerFormatter: PropTypes.func.isRequired,
    }
    
    const TableColumns = props => {
        const { data, columnNames, formatter } = props
        return (
            <tdoby>
                {data && columnNames &&
                    data.map(item => (
                        <tr key={item.id}>
                            {columnNames.map(key => (
                                <td key={item.id}>{formatter(key, item[key], item.id)}</td>
                            ))}
                        </tr>
                    ))}
            </tdoby>
        )
    }
    TableColumns.propTypes = {
        data: PropTypes.arrayOf(PropTypes.object).isRequired,
        columnNames: PropTypes.arrayOf(PropTypes.string).isRequired,
        formatter: PropTypes.func.isRequired,
    }
    
    const TableContainer = ({ data, headers, columnNames, formatter, headerFormatter }) => (
        <Table responsive>
            <TableHead data={header} headerFormatter={headerFormatter} />
            <TableColumns data={data} columnNames={columnNames} formatter={formatter} />
        </Table>
    )
    TableContainer.propTypes = {
        headers: PropTypes.arrayOf(PropTypes.string).isRequired,
        headerFormatter: PropTypes.func.isRequired,
        columnNames: PropTypes.arrayOf(PropTypes.string).isRequired,
        formatter: PropTypes.func.isRequired,
        data: PropTypes.arrayOf(PropTypes.object).isRequired,
    }
    
    export default TableContainer

          总结: 

           细心的同学不难发现,首先有许多重复的代码, TableContainer.propTypes TableHeader.propTypes  TableColumns.propTypes

           对于header,如果这么写,header就显示同样的format,不能实现对表头每一个名称进行个性化的定制。

           body同样的道理,使所有的行得每个元素都具有相同的format,或者在使用此component时,需要进行大量的判断,根据不同的字段,赋予不同的format。这种component简直有同于无。 

           很明显,不改进,codeReview肯定过不了。

    2.第二个react table component 

    import React from 'react'
    import PropTypes from 'prop-types'
    import { Table } from 'react-bootstrap'
    import { RowHead } from './style'
    
    
    const HeaderCell = props => {
        const { header, headerFormatter } = props
        return <th> {headerFormatter ? headerFormatter(header) : header} </th>
    }
    const HeaderCellPropTypes = {
        header: PropTypes.arrayOf(PropTypes.string).isRequired,
        headerFormatter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired,
    }
    HeaderCell.propTypes = HeaderCellPropTypes
    
    const ColumnCell = props => {
        const { value, formatter, coluumnId } = props
        return <td> {formatter ? formatter(value, coluumnId) : value}</td>
    }
    ColumnCell.propTypes = {
        value: PropTypes.string.isRequired,
        formatter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired,
        coluumnId: PropTypes.string.isRequired,
    }
    
    const TableContainer = ({ cloumns, data }) => (
        <Table responsive>
            <thead>
                <RowHead>
                    {cloumns &&
                        cloumns.map(item => (
                            <HeaderCell
                                key={item.header}
                                header={item.header}
                                headerFormatter={item.headerFormatter}
                            />
                        ))}
                </RowHead>
            </thead>
            <tbody>
                {data && cloumns && data.map(item => (
                    <tr key={item.id}>
                        {cloumns.map(cell => (
                            <ColumnCell
                                key={item.id}
                                coluumnId={item.id}
                                formatter={item.formatter}
                                value={item[cell.accessor]}
                            />
                        ))}
                    </tr>
                ))}
            </tbody>
        </Table>
    )
    
    TableContainer.propTypes = {
        cloumns: PropTypes.arrayOf(
            PropTypes.shape({
                ...HeaderCellPropTypes,
                accessor: PropTypes.oneOf(PropTypes.func, PropTypes.string),
                formatter: PropTypes.oneOfType([PropTypes.func, PropTypes.element]).isRequired,
            })
        ).isRequired,
        data: PropTypes.arrayOf(PropTypes.object).isRequired,
    }

    分析: 第一个Component的所有的不足,在第二个component中变成了优势。good

    export default ReactTableComponent

    我们不一样
  • 相关阅读:
    举例一个IO多路复用的C/S例子
    简单介绍协程
    生产者消费者模型
    多进程介绍
    有关多线程(同步锁,递归锁,同步对象,信号量)
    threading多线程模块
    开发一个支持多用户在线的FTP程序
    NTP时间服务器与客户端
    EF之增删改查
    返回新插入的数据的主键ID
  • 原文地址:https://www.cnblogs.com/bug-mark/p/10099951.html
Copyright © 2020-2023  润新知