Vant 骨架屏头像占位组件 SkeletonAvatar 实战指南:属性、源码实现与主题定制
2026/9/12 10:39:32 网站建设 项目流程

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-skeletonavatar属性渲染结果或自定义模板(#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),后面跟随标题行和三行段落占位。avatartitle: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, }; }, };

loadingtrue时展示骨架占位,为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 | string32px
avatar-shape头像占位的形状,可设为squarestringround

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(如50width: 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-skeletonavatar-shapeavatar-size属性会原样透传给SkeletonAvatar,两个组件的同名属性保持一致的语义。

样式与主题定制

SkeletonAvatar 的样式定义在 index.less,对外暴露两个 CSS 变量:

变量名默认值说明
--van-skeleton-avatar-size32px头像占位尺寸
--van-skeleton-avatar-backgroundvar(--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,覆盖两个场景:

  1. 无属性渲染:断言默认输出<div class="van-skeleton-avatar van-skeleton-avatar--round">
  2. 属性变更渲染:传入avatarSize: 50avatarShape: '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-sizeavatar-shape两个属性,但它在 Vant 骨架屏体系中承担着关键的布局职责:既可以通过van-skeletonavatar属性一键启用,也可以在#template插槽中自由组合,还能通过 CSS 变量实现主题定制。配合其极简的源码实现(单div+bem类名 + 内联尺寸样式),开发者可以快速掌握其渲染原理,并将其灵活运用于信息流、用户卡片、商品列表等各类加载场景。

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询