自定义table表格组件化整理

   大家好,最近天冷了,注意多穿衣服保暖哟

   最近接到了这样一个需求,大概就是画出来一个机票行程单这样的页面。看到这个页面大家首选方案是什么table还是div+css3,我首选方案是table。因为这个页面除了表格稍微复杂了点,其他都很简单。用div+css3的话还需要调试样式再各大浏览器的兼容性,注定是要写超多的css样式。而table完全不需要担心,何必多次一举呢。我们的口号是用最简单的编码逻辑实现最复杂的功能,能写一行代码实现的功能坚决不写两行代码实现。

   接下来就要用到table表格了,再使用table表格的时候要确定好表格的行和列,下边这个看着好像挺简单的,但是要是确定行数和列数肉眼还是看不出来的。因此这里我特地用excel先做了一个这样的表格出来,这样就很快可以确定出表格的行和列,每个单元格所占的行和列也就快速确定出来了,确定好之后就可以愉快的画我们的table了。表格画好之后,有些宽度和高度可能需要重新设置下就好了,再调下颜色和字体,完美解决了。
    

当然不止这一种车票用这样的形式,还有客运汽车票和火车票也是用的原生table来画的。项目中使用的react开发的,做的过程中发现都是使用的原生table,那是不是可以把table这一部分提取成一个组件来使用呢。说干就干,提取过程中首先就是确定好参数,确定好是要渲染tr还是td还是th标签,确定好之后,用循环来渲染table中的行和列就可以了。

贴下代码

table.jsx
import React from 'react';
import PropTypes from 'prop-types';
import Item from './RenderItem';

const Table = ({ tableList }) => {
  return (
    <div>
      <table>
        <tbody>
          {tableList.map((item) => (
            <tr align={item.align} key={item.id}>
              {item.children.map((childItem) => (
                <Item
                  key={childItem.data}
                  type={item.type}
                  isPrice={childItem.isPrice}
                  isTitle={childItem.isTitle}
                  {...childItem}
                />
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};
Table.propTypes = {
  tableList: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      isParent: PropTypes.bool,
      type: PropTypes.string,
      align: PropTypes.string,
      children: PropTypes.arrayOf(
        PropTypes.shape({
          data: PropTypes.string,//唯一key值
          width: PropTypes.string,//单元格宽度
          content: PropTypes.string,//单元格内容
          isPrice: PropTypes.bool,//是否是价格的单元格,后续可能需要
          isTitle: PropTypes.bool,//是否是标题的单元格,后续可能需要
          className: PropTypes.string,//单元格的class属性
          colSpan: PropTypes.string,//所占的列数
          rowSpan: PropTypes.string,//所占的行数
        }),
      ),
    }),
  ),
};
Table.defaultProps = {
  tableList: [],
};
export default Table;


//RenderItem.jsx
import React from 'react';
import PropTypes from 'prop-types';

const Item = ({ type, isTitle, isPrice, ...rest }) => {
  if (type === '0') {
    return <th {...rest}>{rest.content}</th>;
  }
  if (type === '1') {
    return <td {...rest}>{rest.content}</td>;
  }
  return <td {...rest}>{rest.content}</td>;
};
Item.propTypes = {
  type: PropTypes.string.isRequired,
  isTitle: PropTypes.bool,
  isPrice: PropTypes.bool,
};
Item.defaultProps = {
  isTitle: false,
  isPrice: false,
};
export default Item;


//参数格式如下所示
const list = [
    {
      id: '1',
      isParent: true,
      type: '0',
      align: 'center',
      children: [
        {
          data: '1',
          colSpan: '2',
          rowSpan: '2',
          height: '80px',
          content: '',
          isPrice: false,
        },
        {
          data: '2',
          width: '105px',
          content: '姓名',
          isPrice: false,
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '3',
          width: '175px',
          content: '身份证',
          isPrice: false,
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '4',
          width: '115px',
          rowSpan: '2',
          content: '票价',
          isPrice: false,
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '5',
          rowSpan: '2',
          colSpan: '2',
          width: '240px',
          content: selectInvoice.fare,
          isPrice: true,
        },
      ],
    },
    {
      id: '2',
      isParent: true,
      type: '1',
      align: 'center',
      children: [
        {
          data: '1',
          content: selectInvoice.passengerName,
          isTitle: false,
        },
        {
          data: '2',
          content: '',
          isTitle: false,
        },
      ],
    },
    {
      id: '3',
      isParent: true,
      type: '0',
      align: 'center',
      children: [
        {
          data: '1',
          width: '120px',
          height: '40px',
          content: '乘车日期',
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '2',
          width: '120px',
          height: '40px',
          content: '乘车时间',
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '3',
          content: '座位号',
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '4',
          content: '检票口',
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '5',
          content: '车次',
          isTitle: true,
          className: styles['text-color'],
        },
        {
          data: '6',
          width: '240px',
          content: '座位类别',
          isTitle: true,
          className: styles['text-color'],
        },
      ],
    },
    {
      id: '4',
      isParent: true,
      type: '1',
      align: 'center',
      children: [
        {
          data: '1',
          height: '40px',
          content: byDate,
        },
        {
          data: '2',
          height: '40px',
          content: '',
        },
        {
          data: '3',
          height: '40px',
          content: '',
        },
        {
          data: '4',
          height: '40px',
          content: '',
        },
        {
          data: '5',
          height: '40px',
          content: selectInvoice.toolsNumber,
        },
        {
          data: '6',
          height: '40px',
          content: '',
        },
      ],
    },
  ];


再写成组件的时候,出现了一个错误,虽然可以正常显示,但是控制台一直打印错误

Warning: Failed propType: checker is not a function Check the render method of Chart

  就是这么个错误,当时就有点懵逼,这个checker 并没有定义啊,为什么会报错呢。后来再stackover上找到了类似的错误,下边也给出了解决方案。最后发现是使用PropTypes定义变量的时候,变量的类型给搞错了。最后修改过来完美解决。

     整理下提取组件的思路

    1、可以先再不提取的情况下画出完整的页面,然后确定页面中哪些部分是可以抽取出来给组件化的

    2、确定好组件需要的参数,哪些是必需的,哪些是非必需的

    3、如果只是简单的查看不需要对组件操作,直接返回一个界面就可以的。如果页面中有需要操作的,可以使用useRef的形式达到父子组件间传值

以上只是个简单的提取组件的案例,再接下来的开发中再接再厉,争取可以有更多组件化开发的思想和实践。我再优化下这个组件,争取能发到公共的npm库上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值