浅谈数栈产品里的 Descriptions 组件

我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。
本文作者:修能

What's?

数栈产品里的 Descriptions 组件实际上就是 antd 的 Descriptions 组件,那么 antd 的 Descriptions 组件是什么?

在数栈产品中,我们通常使用的方式是 bordered + small 的模式。

即:

tsx 复制代码
<Descriptions bordered size="small">
  <Descriptions.Item label="任务名称">
    {taskName}
  </Descriptions.Item>
  <Descriptions.Item label="指标表名称">
    {tableName}
  </Descriptions.Item>
</Descriptions>

展示如下:

平平无奇,甚至非常普通。但,这里面暗藏玄机。

Why?

我们要实现一行只有一个 Item 的设计方式。这里我们可以借助 Descriptions 组件的 column API 实现。

diff 复制代码
 - <Descriptions bordered size="small">
 + <Descriptions bordered size="small" column={1}>

此时,一位靓仔发出疑惑:"怎么就这么宽了?"

那么,直接根据设计稿的尺寸给设置宽度吧

tsx 复制代码
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

相关推荐
雯0609~11 分钟前
网页F12:缓存的使用(设值、取值、删除)
前端·缓存
℘团子এ14 分钟前
vue3中如何上传文件到腾讯云的桶(cosbrowser)
前端·javascript·腾讯云
学习前端的小z20 分钟前
【前端】深入理解 JavaScript 逻辑运算符的优先级与短路求值机制
开发语言·前端·javascript
彭世瑜44 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4041 小时前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish1 小时前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five1 小时前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序1 小时前
vue3 封装request请求
java·前端·typescript·vue
临枫5411 小时前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
前端每日三省1 小时前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript