Skip to content

Skeleton 骨架屏 ​

17:06

说明 ​

数据加载期间的占位骨架。loading=true 时按 avatar / title / rows 渲染对应的灰色占位块,loading=false 时改为渲染默认插槽的真实内容,实现原位替换;animate 控制各占位块内的扫光动画。

兼容性 ​

平台支持情况
App✅ 支持(扫光由 UniElement.animate 逐条驱动,渐变降级为单向两色)
H5✅ 支持(扫光由 CSS @keyframes 驱动)
微信小程序✅ 支持(扫光由 CSS @keyframes 驱动)

示例 ​

基础用法 ​

默认展示标题 + 段落占位图,loading=true 时显示骨架。

查看源码
vue
<template>
    <ux-skeleton :loading="true" :rows="3" />
</template>

段落行数 rows ​

通过 rows 设置段落占位图的行数。

查看源码
vue
<template>
    <ux-skeleton :loading="true" :rows="rows" />
    <view class="btn-wrap">
        <ux-button v-for="(item, index) in rowsList" :key="index" :type="rows === item.value ? 'primary' : 'default'" custom-class="btn-item" @click="rows = item.value">{{ item.label }}</ux-button>
    </view>
</template>

<script setup lang="uts">
const rows = ref<number>(3);

const rowsList = [
    { value: 2, label: '2' },
    { value: 3, label: '3' },
    { value: 5, label: '5' }
];
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    margin-top: 10px;
}
.btn-item {
    margin-right: 12px;
}
</style>

自定义宽度/高度 ​

rows-width / rows-height 支持数组按行设置,title-width / title-height 设置标题尺寸。

查看源码
vue
<template>
    <ux-skeleton :loading="true" :rows="3" :rows-width="['100%', '80%', '60%']" :rows-height="['25', '25', '25']" :title-width="'40%'" :title-height='30' />
</template>

头像 avatar ​

avatar=true 显示头像占位图,avatar-shape 支持 circle / square。

查看源码
vue
<template>
    <ux-skeleton :loading="true" :rows="3" avatar :avatar-size="20" avatar-shape="circle" />
</template>

动画开关 animate ​

animate 控制扫光动画,可点击按钮切换开/关对比效果。

查看源码
vue
<template>
    <ux-skeleton :loading="true" :rows="3" :animate="animate" />
    <view class="btn-wrap">
        <ux-button :type="animate ? 'primary' : 'default'" @click="animate = !animate">{{ animate ? '开启动画' : '关闭动画' }}</ux-button>
    </view>
</template>

<script setup lang="uts">
const animate = ref<boolean>(true);
</script>

<style scoped>
.btn-wrap {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    margin-top: 10px;
}
</style>

列表场景 ​

模拟消息/文章列表骨架,多卡片各自扫光,观感接近真实页面。

查看源码
vue
<template>
    <view class="list">
        <ux-skeleton v-for="(item, index) in sceneList" :key="index" custom-class="list-item" avatar title :rows="3" :rows-width="['100%', '90%', '62%']" :rows-height="['16', '16', '16']" :title-width="'32%'" :title-height="'22'" />
    </view>
</template>

<script setup lang="uts">
const sceneList = [1, 2, 3];
</script>

<style scoped>
.list {
    display: flex;
    flex-direction: column;
}
.list-item {
    margin-bottom: 12px;
    padding: 14px;
    background-color: #ffffff;
    border-radius: 8px;
}
</style>

加载完成 loading ​

loading=false 时隐藏骨架,显示真实内容;骨架结构与真实内容一一对应,加载后原位替换。

查看源码
vue
<template>
    <ux-skeleton :loading="loading" title avatar :rows="3" :rows-height="['18', '18', '40']" :title-height="'22'">
        <view class="card">
            <view class="card__avatar"></view>
            <view class="card__body">
                <text class="card__title">uView Pro 组件库</text>
                <text class="card__line">丰富的组件覆盖开发过程各类需求,多端兼容,开箱即用。</text>
                <text class="card__line">组件功能完善,样式与全局主题均支持自定义。</text>
                <text class="card__line">示例代码一键复制,快速集成进你的项目。</text>
            </view>
        </view>
    </ux-skeleton>
    <view class="wrap">
        <ux-button :type="loading ? 'primary' : 'default'" shape="round" @click="loading = !loading">{{ loading ? '切换加载中' : '加载完成' }}</ux-button>
    </view>
</template>

<script setup lang="uts">
const loading = ref<boolean>(true);
</script>

<style scoped>
.wrap {
    display: flex;
    flex-direction: row;
    margin-top: 10px;
}
.card {
    display: flex;
    flex-direction: row;
    align-items: flex-start;
    width: 100%;
    padding: 12px;
    background-color: #ffffff;
    border-radius: 8px;
}
.card__avatar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: #2979ff;
    margin-right: 12px;
    flex-shrink: 0;
}
.card__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 1;
}
.card__title {
    font-size: 16px;
    font-weight: bold;
    color: #323233;
    margin-bottom: 8px;
}
.card__line {
    font-size: 13px;
    line-height: 20px;
    color: #606266;
    margin-bottom: 4px;
}
</style>

API ​

Props ​

属性说明类型默认值版本
customStyle自定义根节点样式string | UTSJSONObject--
customClass自定义根节点样式类string''-
loading是否显示骨架占位图booleantrue-
animate是否开启动画效果booleantrue-
rows段落占位图行数string | number0-
rowsWidth段落占位图的宽度string | number | string[]'100%'-
rowsHeight段落的高度string | number | string[]18-
title是否展示标题占位图booleantrue-
titleWidth标题的宽度string | number'50%'-
titleHeight标题的高度string | number18-
avatar是否展示头像占位图booleanfalse-
avatarSize头像占位图大小string | number32-
avatarShape头像占位图的形状string'circle'-

Events ​

ux-skeleton 无事件。

Slots ​

插槽名说明版本
defaultloading=false 时展示的真实内容-

注意事项 ​

  • loading=false 时才渲染默认插槽内容;骨架与真实内容需自行保持结构一致,否则切换时会跳动。
  • rows-width / rows-height 传数组时按行索引取值;数组长度不足时,宽度最后一行取 70%、其余 100%,高度统一取 18。
  • animate 仅在 loading=true 时可见;扫光在每个占位块内裁剪(overflow: hidden),不会铺到块间空隙。
  • App 端不使用 @keyframes,扫光由 UniElement.animate 逐条驱动,且 linear-gradient 仅支持方向 + 两色,渐变较 H5 / 小程序更简单。
  • avatar-shape 支持 circle(默认)与 square(4px 小圆角)。