浅谈数栈产品里的 Descriptions 组件
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。
本文作者:修能
What's?
数栈产品里的 Descriptions 组件实际上就是 antd 的 Descriptions 组件,那么 antd 的 Descriptions 组件是什么?
在数栈产品中,我们通常使用的方式是 bordered + small 的模式。
即:
<Descriptions bordered size="small">
<Descriptions.Item label="任务名称">
{taskName}
</Descriptions.Item>
<Descriptions.Item label="指标表名称">
{tableName}
</Descriptions.Item>
</Descriptions>
展示如下:
平平无奇,甚至非常普通。但,这里面暗藏玄机。
Why?
我们要实现一行只有一个 Item 的设计方式。这里我们可以借助 Descriptions 组件的 column API 实现。
- <Descriptions bordered size="small">
+ <Descriptions bordered size="small" column={1}>
此时,一位靓仔发出疑惑:“怎么就这么宽了?”
那么,直接根据设计稿的尺寸给设置宽度吧
contentStyle={{
width: 630,
}}
labelStyle={{
width: 140,
}}
可以?不可以!由于我们这个模块是在详情的抽屉里,抽屉的宽度是不固定的,那么这里设置固定值会导致有问题!……有问题吧?
这里的 label 宽度并没有按照所设置的来,而是自适应的撑满了。
但是,都是自适应,这里的自适应并不是我们想要的,根据 UI 设计师的确认,这里的自适应应该是 label 的大小不变,content 的大小自适应。
怎么实现?
设置 contentStyle 的 width 为 'calc(100% - 140px)'
看起来,这个需求搞定了?实际上,还有问题!
这里,我们需要模拟一下任务名称很长并且用 Button
组件的情况。
这里,我们想到,可以用 EllipsisText 组件解决溢出省略的问题。
糟糕,貌似并没有生效,这是为何?
分析原因如下:
这里我们一下原因,首先,我们这里的省略逻辑是如下
- 通过设置 maxWidth 为百分比(不能设置具体数值,为何?),然后配合 overflow
我们从 DOM 树上可以看出来,理论上,我们应该是 td 元素的宽度百分比,同时 td 元素设置的宽度也是百分比,所以理论上是 tr 元素的百分比。
这里我们发现,tr 元素的宽度并没有按照我们设想的是继承父元素的宽度,而是被子元素撑开了。那么,我们尝试在 tr 上增加 width:100%
使其宽度为继承父元素的宽度。
还是无效,这是为何?
我们这里注意到,width 是需要继承父元素的宽度,而父元素的宽度也是被撑开的。这里我们省略一些定位的过程,快进到定位 table 元素。
这个 Descriptions 组件的根元素是 table 元素。table 元素相比起普通的 div 元素来说,更加复杂,其相关的 CSS 属性更加难以捉摸。
观察到,这里的 table 组件上有如下属性
table 的宽度被设置了 100%,但是并没有继承父元素的宽度,而是被子元素撑开了。
这里我们注意到 table 有一条属性为 table-layout,在 MDN 中该属性的定义为:
table-layout CSS 属性定义了用于布局表格的单元格、行和列的算法。
如果设置为 auto,则表示
默认情况下,大多数浏览器使用自动表格布局算法。表格及其单元格的宽度会根据内容自动调整大小。
到这里就破案了,如果设置为了 auto,则单元格会根据内容自适应,那么就会导致父元素(即单元格)会被子元素的宽度撑开,即使给父元素的宽度设置了一个固定值也会失效。
如果表格布局是 auto,表格将会根据其内容自动扩展大小,而不考虑指定的 width
那么,可以确认,如果我们想要用 Descriptions 组件实现文案的省略,则不可避免地需要将 table-layout 设置为 fixed 属性。
How
然而,Descriptions 组件默认的 table-layout 是为 auto,且并没有相关的属性去修改这个值。
所以这里我们只能通过全局的 CSS 去修改?(theme 可做)
但这里,我选择在指标里重写 Descriptions 组件,让用户可控地去使用 Descriptions 组件。
题外话,需要插入说明一下,如果 table-layout 设置为 auto,且单元格的内容并没有溢出,即一开始设置的那样子。那么此时单元格的宽度其实并非我们设置的值,而是基于我们给不同单元格设置的 width 计算出的比例进行等比放大或缩小。
例如:我现在给单元格分别设置 140px 和 280px。
此时若 table 宽度恰好为 420px,则 label(即 th 元素)恰好为 140px,content(即 td 元素)恰好为 280px。
若 table 宽度大于 420px,则按照 1:2 的方式等比放大。
此时 table 的宽度为:
计算可得:806 * 1/3 ≈ 248。
最后
欢迎关注【袋鼠云数栈UED团队】~
袋鼠云数栈 UED 团队持续为广大开发者分享技术成果,相继参与开源了欢迎 star