使用flex和div布局实现表格的解决方法(类似天眼查那种)

2022-09-15  本文已影响0人  mudssky

使用flex和div布局实现表格的解决方法(类似天眼查那种)

因为业务需求,几个地方用到类似天眼查工商信息那种表格.

最初我是用table写的,然后我发现很麻烦,假设像天眼查一样有几十个字段,那么表格的tsx就要写一大坨.再加上表单,工作量可以说是非常大了.而且没有可复用性.

其他地方本来也要用到类似的表格,

(但是最后我发现还是用table方便,虽然没有复用性,但是至少改起来很容易.进行封装以后你会发现改起来很麻烦,需求稍微变动一点,你这边搞起来都很麻烦.还有一些不好处理的bug,反正你这个组件目前只有固定几个地方会用到.复制粘贴也是很快的)

第二版我就改成用flex布局实现了.

使用了antd的栅格组件Row和Col.本质上是flex布局的效果.

采用类似配置表单的方式,直接遍历列表,把对应的格子渲染出来,

然后Row设置flex-wrap,这样内容超出的时候就会换行.我们可以控制每个格子的span值,控制表格每行的显示

表格的每一个条目都是像表单一样包含label和content,

然后表格的边框,可以先设置Row的左边框和上边框,然后设置每个格子的右边框和下边框,这样的效果就是类似表格的边框

使用col的span属性划分

第一个问题

很快就碰到第一个问题,就是表格的合并单元格,这个本来我是用span划分空间的,但是碰到不是整数的情况,就会发现表格的格子对不齐

解决方案就是用Col组件的flex属性,每个格子设置成固定flex值.

第二个问题 缩放时发生换行

缩放时发生换行,导致最后一个格子换行到第二行,表格发生变形

也就是浏览器的ctrl+滚轮的缩放功能,这个bug过了好几个月才被发现.因为一般人不会缩小网页,一般是放大网页,放大的时候表格没有异常.

其实应该不是很影响使用,因为缩放到70%的时候才发生换行.

第一个解决方案,增大Row的宽度

很容易想到,只要我们增大Row的宽度,那么就不会换行了,

这个方案主要的影响是,border-top会有一点点超出表格边界的部分.

这个多余的border其实也有办法消除,拿一个别的元素遮一下就行了.

我觉得这样不太好.很蠢

第二个解决方案,单独设置每个单元格的border

我们去掉Row的border设置,然后我们传入每个格子信息的时候,顺便设置每个格子的border

因为Row和Col组件默认是border-box盒模型的,也就是border也计算在width里,

所以我们单独设置border并不会撑大表格.

这个也很蠢,写那么多样式代码,不如不封装

第三个解决方案 conten-box

终于我发现问题的根本所在,因为Row是border-box盒模型,所以给它设置border会挤压内部的格子的空间

所以我们flex设置的值不正确,我们以为每一行格子的宽度是1200px,实际上,由于设置Row的border,每一行格子拥有的宽度是1199px

所以我们把Row的盒模型,设置为

box-sizing:content-box

这样只改了一行代码,问题就解决了.

宽度自适应的问题

其实一开始没有找到自适应的方法,所以我才改成设置表格固定宽度的方案

不过现在我已经知道如何正确设置了。

flex布局里空间的分配

虽然一直都用flex布局,但是其实一直没有完全理解。

基本上都是flex:1 flex:宽度flex:auto这几个值在用。

也就是说,用的基本上只用到一个属性,另外两个flex-grow和flex-shrink都是自动推算的,从来没主动设定过,而且完全没感觉到需要用这两个属性的地方。

确实完全不影响使用。

flex-shrink 属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

flex 属性属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。

其实flex:1 实际上是 flex: 1 1 0%; lex:auto = flex: 1 1 auto; 这两个平时区别不大,只是flex:1 flex-basis为0% 这种方式会覆盖原来的width

所以平时还是auto会好一点。

但是我因此误解了,以为 flex:1flex:8这样也能工作,实际是不能工作的。

flex整数的情况下只支持0和1.

其他情况需要设置宽度,

所以我们用百分比可以正常分配

    formLayout: {
      labelCol: { flex: 'calc(100% / 9)' },
      wrapperCol: { flex: 'calc(100% - 100%/9)' },
    },

这样表格分配空间就不像用Col组件,只能用span,在24以内的整数里面分配

span的情况, 样式会变成 ant-col-2.6666666666666665,antd还是不支持这种的。

这种情况用flex属性会更灵活。

思考

在table里面实现这个边框还是很简单的,

th,td都设置边框,但是还有一个border-collapse属性,使得表格边框之间不发生重叠.

但是拿div实现表格边框就很麻烦,flex布局下没有方便的css属性.

上一篇下一篇

猜你喜欢

热点阅读