骨架屏优化——细粒度模式的实现

3,633 阅读4分钟

无声同学是我们 DevUI 开源组件库的田主,从2021年9月份进入 DevUI 开源组织到现在,一直在持续贡献,为 Skeleton / Table / Avatar 等多个组件贡献过代码,累计提交次数达到 53 次。

image.png

感谢无声同学的辛勤付出,在参与 DevUI 开源项目的过程中,不仅积极调研业界竞品,积极主动地确认组件开发的细节,而且沉淀了多篇技术文章,以下就是他在开发 Skeleton 骨架屏组件时沉淀的其中一篇文章。

除了无声同学,还有很多小伙伴参与到 DevUI 开源项目中来,并且都有自己的收获,也欢迎大家参与我们的 Vue DevUI / React DevUI / Ng DevUI 等多个开源项目,一起学习和成长!(添加 DevUI 小助手微信:devui-official

以下是正文:

前言

之前总结了给 DevUI 开发骨架屏(Skeleton)的一些心得:

记录我的第一个开源组件

Kagol 老师看到之后提出增加拼接模式。之所以到现在才更新,一方面是因为最近换了个项目组,另一方面是思考如何设计 API 让两种模式风格统一(才不是因为 lol 手游和云顶 S6 的关系)。

图片

两种颗粒度

粗粒度模式

默认模式即粗粒度模式,也可以看作是细粒度的拼接模式。这个模式下,骨架屏大致包含头像、标题、段落,如下图所示。

图片

细粒度模式

即指完整的骨架屏被拆成细粒度的骨架屏元素,从图形的角度可以分为圆形和矩形,从功能的角度可以分为占位头像、占位图像、占位标题、占位内容、占位按钮。

图片

比较

相比默认模式,细粒度的骨架屏元素给使用这个组件的开发者提供了更大的灵活和定制能力。市面上,Element-ui 和 Vant-ui 采用默认模式,抖音的 SemiDesign 采用拼接模式,Antd 则兼具二者。似乎 React 的组件库会更倾向于细粒度?

API设计

默认模式下,由于多个元素被包裹在根节点下,不方便直接设置样式,所以提供了许多样式 API 。而在拼接模式下,由于本身就是多根节点,类似宽高等样式可以直接通过 style 去控制,再设计额外的 API 就显得多余。

非Prop的Attribute

当我尝试直接通过 style 去控制组件的样式时,控制台报了警告,而之前在默认模式下没有这个问题,我又试了试 ICON 组件发现了同样的问题。

图片

起初我还以为这是项目没有做相关配置的问题,后来在行言同学的指导下发现了问题。

图片

Vue 3 文档的表述是:一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 props 或 emits 定义的 attribute。常见的示例包括 classstyleid attribute。可以通过 $attrs property 访问那些 attribute。

在 JSX 中用ctx.attrs来传入,具体如下:

<div
  class={`devui-skeleton__shape__${props.shape} ${renderAnimate(props.animate)}`}
  {...ctx.attrs}
/>

实现

第一版 PR 尽管在功能上实现了,但在 code review 的时候给打回了,原因在于两种模式放在同一个文件下导致内容太大,功能比较杂乱。

Kagol 眼中的理想的模式应该是:

  1. 将骨架屏划分成d-skeletond-skeleton-item
  2. d-skeleton组件其实只是将d-skeleton-item拼接起来,我们可以内置一些拼接模式,这部分和目前实现的API可以保持一致。

因此我将拼接模式的代码拆分到 item 文件夹下,再在 index 中通过 app.component注册组件。最终单个 TSX 文件长度控制在了 150 行以内。

import type { App } from 'vue'
import Skeleton from './src/skeleton'
import SkeletonItem from './src/item/item'

export { Skeleton, SkeletonItem }

export default {
  title'Skeleton 骨架屏',
  category'数据展示',
  status'100%',
  install(appApp): void {
    app.component(Skeleton.nameSkeleton)
    app.component(SkeletonItem.nameSkeletonItem)
  }
}

参考

  1. 非 Prop 的 Attribute: v3.cn.vuejs.org/guide/compo…
  2. Vue3 JSX 使用指南: mp.weixin.qq.com/s/SNC5pq89N…

闲谈

秀下 DevUI 发的抱枕(掘金的徽章啥时候才能到呢)

图片

原文链接:mp.weixin.qq.com/s/DkqUyTZ-U…

作者:无声(欢迎关注无声同学的公众号前端手记