时间选择器组件之关于table走过的弯路

1,396 阅读7分钟

为了提高开发者的研发效率,提升产品品质,我们提供一套基于饿了么UI实现的UI组件库,TMAP-UI---旨在解决的组件地图场景下应用的问题。

最近在新增TMAP-UI组件库的开发过程中,时间选择器是开发者反馈需求较多的一个组件,今天把在开发过程中遇到的一些问题分析给大家。element-ui有原生的时间选择器,但是,在我们的交互设计师是根据地图实际应用场景中的特性抽象组件,element-ui的样式以及交互操作都无法满足设计需求,需要基于源码进行二次开发,最小成本实现这个通用组件。今天主要聊下开发中遇到的一些关于table的实现问题,对table一探究竟…

关于table特点

首先,我们先来基本了解一下table。

<table>
    <caption>A summary of the UK's most famous punk bands</caption>
    <thead>
        <tr>
            <th scope="col" class="fixed-width-test2">Band</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th scope="row">Buzzcocks</th>
            <td>1976</td>
            <td>9</td>
            <td>Ever fallen in love (with someone you shouldn't've)</td>
        </tr>
    </tbody>
</table>

一个基本的table布局主要由tabletbodythtd等标签组成。W3C标准中,table的每个标签都自带了display样式。例如td标签默认就会有display:table-cell的样式,在这个默认样式下,新增margin的设置是不会生效的。更详细标签对应样式可以查看W3C标准

关于时间选择器

时间选择器设计图

根据上图为设计师给出的时间选择器的设计图,选择时间范围是一个重要的新增功能。

实现它的步骤拆分成以下几步:

  • 1.实现基本表格布局

  • 2.添加日期范围选择的样式

实现基本表格布局

首先我们需要按照设计图调整日期间的间距和每个日期的单元格大小。所以,需要对于每个子格设置宽、高和margin进行布局。

从上图左侧可以看出,样式在style成功设置的情况下,右侧盒模型的宽和margin都没有生效。

我首先猜测是不是哪里的样式压盖了,又或者是样式本身因为某些原因导致没有生效。

于是使用常用的样式压盖方法,在没生效的样式后添加!important来提高设置样式的优先级,但还是没有生效。

后来查了W3C的关于table的设置说明,发现了上文提到的td自带的display:table-cell样式。于是尝试在样式中新增display:block替代原有table自带样式。果然当我设置之后,子td的宽高和margin都生效了。

查阅资料之后发现,一方面td标签不允许设置margin,另一方面,在table整体的宽度设定后,样式不会按照td标签中设置的宽度执行,会按照整体的table宽度均分给每一个子td。如果希望一些特殊的效果,对宽度设置百分比是可以生效的。这其实能够理解,如果在table-cell的模式下允许某个子模块设置宽度和margin,会导致子模块的宽度和高度不可预期,对同一行的其他子块的宽高造成影响。总结下,为了保证table的样式整体联动性,table宽高和子td的宽高设置不能同时使用绝对数值来设置,只能设置其中一个绝对值,另外一个用相对值来计算划分。

如果我们通过display:block完成格式,整体的表格结构就会被打破,产生更多不符合表格逻辑预期的样式问题。于是我们通过每个子单元格均分的特性,设置总的行宽和行高来控制单元格自身的大小和之间的距离,从而达到实现整体表格布局的效果。

添加日期范围和选择样式

  • 盒子宽度问题

那当我们hover态的盒子和背景颜色的盒子大小不一样的时候,我们就需要在td的内部内置一个盒子。这样通过设置颜色我们就可以实现背景。按照上述,只要我们设置好整体的table宽度和背景颜色,就可以得到日期选中范围的设计背景效果,对应的背景颜色得到如下结果。

设定整体宽度之后,我们发现部分子td之间存在一条深色的边界线。这是由于他们之间出现了互相压盖,整体的七个td的总宽度设计稿给出是242px,按照预期是应该七个子模块均分宽度。但我查看具体每个子td的宽度发现,有的子td宽度是34、有的是35。这也就是说,在宽度不能够被子模块整除均分的情况下,table自动为我们做了取整,并且为了保持总宽度的不便,有些被向下取整,有些被向上取整。

目前想到的解决办法是,通过计算固定宽度的总宽度使得每一个td能够被整除。

  • 选中态背景问题

接下来,我们需要解决在选中态下起终点日期的样式问题。按照原有的选中样式无论是否添加背景都不能满足需求。见下图,会出现10号日期右侧空白或26号日期多余背景的情况。

对于起始日期,要完成上述要求,我们需要将起始框以及它的右侧作为块内容并且仍能保证水平居中。解决办法是,对于10号日期的选择起点,将左侧设置margin,右侧设置相应宽度的padding

做到这里基本可以认为完成了一个日期范围选择功能。

但实战发现,还没完......

当用户只选择了起点我们会发现选中态导致右侧的边界还会有蓝色背景色。于是,我们还要利用scss的语法特性为样式设置生效条件来区分两种不同的显示策略。

  • border-radius问题

设计稿要求,每一行的选择框的起始和末尾需要有圆角。这样一个常见的需求,table果然没让我失望,对tr标签设置无效。原因是因为在border-collapse设置为separate下,对于所有table标签设置圆角都无法生效。

查阅资料,找到了两种思路的解决方法。

第一种就是对tr的子td,first-child/last-child设置圆角。讲到这里就不得不提table的一个属性:border-collapse。这个属性用来决定表格的边框是分开的还是合并的。在分隔模式下,相邻的单元格都拥有独立的边框。在合并模式下,相邻单元格共享边框。这里有三个常用值:inherit, separate,collapseseparate表示每个单元格拥有独立的边框,inherit表示相邻的单元格共用同一条边框。

当在separate模式下,我们还可以通过设置border-spacing设置边框的宽度。

w3c border-spacing配图

第二种当设置border-collapse:inherit,便可以设置td和tr的圆角了。

总结

在table布局下,有许多自己样式布局,在我们熟练掌握了之后会发现有很多方便的特性。我也把这次遇到的问题沉淀成了表格,希望能对大家以后的开发有点帮助,少走弯路。

产品推广

地图组件是专为移动端定制的轻应用产品,支持各手机端主流浏览器,可以实现位置展示、路线规划、地图选点、前端定位等多种场景的下的调用。相比于JS API, 可以通过高度参数化的URL直接调用,极大简化开发的复杂度,降低维护成本。欢迎大家体验!