Vant 骨架屏头像占位组件 SkeletonAvatar 实战指南:属性、源码实现与主题定制
【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant
SkeletonAvatar 是 Vant 移动端 UI 库中用于在页面内容加载期间展示头像占位图形的骨架屏组件。本文将围绕该组件的属性配置、底层源码实现、样式定制与测试验证展开,帮助读者在业务中快速落地加载占位效果,并理解其与 Skeleton 骨架屏体系的分工与协作方式。
组件定位:加载过程中的头像占位
SkeletonAvatar 属于 Vant 骨架屏(Skeleton)组件族的一员,与 SkeletonTitle、SkeletonImage、SkeletonParagraph 共同构成一套完整的加载占位解决方案。它专门负责渲染"头像"形态的占位图形,通常配合标题行、段落行一起出现,模拟内容加载完成后的最终布局,降低用户等待时的焦虑感。
官方文档将 SkeletonAvatar 的完整说明统一收敛在 Skeleton 组件文档 中(对应文档中SkeletonAvatar Props一节),这是因为该组件极少单独使用,绝大多数场景下它是作为van-skeleton的avatar属性渲染结果或自定义模板(#template插槽)的一部分出现的。从源码看,Vant 也将其作为独立组件封装并提供导出,便于在自定义骨架屏模板中灵活组合。
安装与注册
SkeletonAvatar 与其他骨架屏组件一样,通过app.use全局注册。参考 Skeleton 文档 中的安装方式:
import { createApp } from 'vue'; import { Skeleton, SkeletonTitle, SkeletonImage, SkeletonAvatar, SkeletonParagraph, } from 'vant'; const app = createApp(); app.use(Skeleton); app.use(SkeletonTitle); app.use(SkeletonImage); app.use(SkeletonAvatar); app.use(SkeletonParagraph);注册后,模板中即可直接使用<van-skeleton-avatar />。关于更多组件注册方式(局部注册、按需引入等),可参考 组件注册指南。
基础用法:通过 Skeleton 的 avatar 属性展示
在绝大多数业务场景中,不需要直接编写<van-skeleton-avatar>,而是给van-skeleton传入avatar属性,由骨架屏组件内部自动渲染头像占位:
<van-skeleton title avatar :row="3" />此时页面会渲染出一个圆形的头像占位(默认 32px),后面跟随标题行和三行段落占位。avatar与title、:row="3"组合,即可快速搭建"用户信息卡片"风格的加载态。
当数据加载完成后,通过loading属性切换为真实内容:
<van-skeleton title avatar :row="3" :loading="loading"> <div>真实内容</div> </van-skeleton>import { ref, onMounted } from 'vue'; export default { setup() { const loading = ref(true); onMounted(() => { loading.value = false; }); return { loading, }; }, };loading为true时展示骨架占位,为false时渲染默认插槽(default)中的真实内容。这一逻辑在 Skeleton.tsx 中实现:当!props.loading时直接返回slots.default?.(),否则渲染骨架屏结构。
自定义模板:在 #template 插槽中组合使用
SkeletonAvatar 的独立价值主要体现在自定义骨架内容场景。van-skeleton提供#template插槽,允许完全自定义占位布局,此时可以按需组合各占位子组件:
<van-skeleton> <template #template> <div :style="{ display: 'flex', width: '100%' }"> <van-skeleton-avatar /> <div :style="{ flex: 1, marginLeft: '16px' }"> <van-skeleton-paragraph row-width="60%" /> <van-skeleton-paragraph /> <van-skeleton-paragraph /> <van-skeleton-paragraph /> </div> </div> </template> </van-skeleton>该示例复刻了"左侧头像 + 右侧多行文字"的典型信息流布局:van-skeleton-avatar负责头像占位,van-skeleton-paragraph配合row-width控制段落宽度。从 Skeleton.tsx 的源码可以看到,renderContents优先渲染slots.template,未提供时才走默认的avatar + content(title + rows)结构。
SkeletonAvatar Props 详解
根据 Skeleton 文档 中SkeletonAvatar Props一节,该组件提供两个属性:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| avatar-size | 头像占位的大小 | number | string | 32px |
| avatar-shape | 头像占位的形状,可设为square | string | round |
avatar-size:控制占位尺寸
- 支持数字(如
50,按 px 处理)与字符串(如'48px'、'20vw')两种写法; - 该值同时作用于宽度与高度,保证头像占位始终为正方形;
- 默认
32px与 CSS 变量--van-skeleton-avatar-size一致,源码中通过getSizeStyle工具将属性值转换为内联width/height样式。
avatar-shape:控制占位形状
round(默认):圆形头像,border-radius使用var(--van-radius-max)(最大化圆角);square:直角方形头像,适合商品图、方形头像等形态。
类型定义在 SkeletonAvatar.tsx 中:
export type SkeletonAvatarShape = 'square' | 'round';同时组件还导出SkeletonAvatarProps类型,可通过如下方式在业务代码中引用:
import type { SkeletonProps, SkeletonImageProps, SkeletonTitleProps, SkeletonAvatarShape, SkeletonImageShape, SkeletonParagraphProps, } from 'vant';源码级实现剖析
SkeletonAvatar 的实现非常精简,完整源码位于 SkeletonAvatar.tsx。核心逻辑如下:
const [name, bem] = createNamespace('skeleton-avatar'); export const skeletonAvatarProps = { avatarSize: numericProp, avatarShape: makeStringProp<SkeletonAvatarShape>('round'), }; export default defineComponent({ name, props: skeletonAvatarProps, setup(props) { return () => ( <div class={bem([props.avatarShape])} style={getSizeStyle(props.avatarSize)} /> ); }, });几个关键实现点:
- props 定义:
avatarSize使用numericProp(数字或字符串),avatarShape使用makeStringProp<SkeletonAvatarShape>('round'),从类型层面约束取值范围; - 渲染结构:组件最终只渲染一个
<div>,通过bem生成van-skeleton-avatar与形状修饰类van-skeleton-avatar--round/van-skeleton-avatar--square; - 尺寸注入:
getSizeStyle来自 utils/format.ts,当传入数字时通过addUnit自动补全为px(如50→width: 50px; height: 50px),传入字符串时原样使用,数组写法则分别映射到宽高。
组件入口 index.ts 使用withInstall包装以支持app.use全局注册,并通过declare module 'vue'声明了VanSkeletonAvatar全局组件类型,从而在模板与 TS 中都能获得完整的类型提示。
与 Skeleton 的集成关系
在 Skeleton.tsx 中,当props.avatar为真时,会渲染:
<SkeletonAvatar avatarShape={props.avatarShape} avatarSize={props.avatarSize} />即van-skeleton的avatar-shape、avatar-size属性会原样透传给SkeletonAvatar,两个组件的同名属性保持一致的语义。
样式与主题定制
SkeletonAvatar 的样式定义在 index.less,对外暴露两个 CSS 变量:
| 变量名 | 默认值 | 说明 |
|---|---|---|
--van-skeleton-avatar-size | 32px | 头像占位尺寸 |
--van-skeleton-avatar-background | var(--van-active-color) | 头像占位背景色 |
完整 CSS 变量清单可参考 Skeleton 文档 的CSS Variables一节(其中--van-skeleton-avatar-size、--van-skeleton-avatar-background即头像相关变量)。默认背景色--van-active-color与骨架屏整体高亮动画一致,保证视觉统一。
在实际渲染中:
- 宽度、高度取
var(--van-skeleton-avatar-size),同时设置flex-shrink: 0防止在弹性布局中被压缩; margin-right: var(--van-padding-md)保证头像与右侧内容留出间距;- 圆形(
--round)形态下使用border-radius: var(--van-radius-max)。
定制示例:将头像占位调整为 48px 的浅灰色圆角方形:
<van-skeleton-avatar avatar-size="48px" avatar-shape="square" style="--van-skeleton-avatar-background: #e8e8e8" />对于整体主题的批量定制,可借助 ConfigProvider 组件 统一注入这些 CSS 变量。
测试验证
组件测试位于 skeleton-avatar/test/index.spec.tsx,覆盖两个场景:
- 无属性渲染:断言默认输出
<div class="van-skeleton-avatar van-skeleton-avatar--round">; - 属性变更渲染:传入
avatarSize: 50、avatarShape: 'square',断言输出<div class="van-skeleton-avatar van-skeleton-avatar--square" style="width: 50px; height: 50px;">。
对应的快照文件为 index.spec.tsx.snap,其中明确记录了数字尺寸50会被规范化为50px这一行为——这正好验证了getSizeStyle+addUnit的尺寸处理逻辑。
小结
SkeletonAvatar 虽然对外只暴露avatar-size与avatar-shape两个属性,但它在 Vant 骨架屏体系中承担着关键的布局职责:既可以通过van-skeleton的avatar属性一键启用,也可以在#template插槽中自由组合,还能通过 CSS 变量实现主题定制。配合其极简的源码实现(单div+bem类名 + 内联尺寸样式),开发者可以快速掌握其渲染原理,并将其灵活运用于信息流、用户卡片、商品列表等各类加载场景。
【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考