Skip to content

当网络加载较慢,或者你希望得到一个过渡性的加载效果时,Skeleton 组件显得尤为合适。

相对比普通的 loading 效果,Skeleton 组件能体现出真实内容的大致轮廓,提供的用户体验会更好!

基本展示

展开查看代码
vue
<template>
    <j-skeleton :loading="true">内容</j-skeleton>
</template>
<template>
    <j-skeleton :loading="true">内容</j-skeleton>
</template>

更多内容

配置avatar属性展示头像占位。

展开查看代码
vue
<template>
    <j-skeleton :loading="true" avatar>内容</j-skeleton>
</template>
<template>
    <j-skeleton :loading="true" avatar>内容</j-skeleton>
</template>

开启动画效果

通过active属性开启动画。

展开查看代码
vue
<template>
    <div>
        <j-switch v-model:checked="loading" style="margin-bottom: 20px" />
        <j-skeleton :loading="loading" avatar active>
            <div>内容</div>
        </j-skeleton>
    </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const loading = ref(true)

setTimeout(() => {
    loading.value = false
}, 3000)
</script>
<template>
    <div>
        <j-switch v-model:checked="loading" style="margin-bottom: 20px" />
        <j-skeleton :loading="loading" avatar active>
            <div>内容</div>
        </j-skeleton>
    </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const loading = ref(true)

setTimeout(() => {
    loading.value = false
}, 3000)
</script>

其他子组件

可供单独使用的子组件。

展开查看代码
vue
<template>
    <div>
        <j-skeleton-image style="margin-top: 20px" active />
        <j-skeleton-title style="margin-top: 20px" active />
        <j-skeleton-paragraph style="margin-top: 20px" active />
        <j-skeleton-avatar style="margin-top: 20px" active />
        <j-skeleton-input style="margin-top: 20px; margin-left: 10px" active />
        <j-skeleton-image style="margin-top: 20px; margin-left: 10px" active />
        <j-skeleton-button style="margin-top: 20px; margin-left: 10px" active />
    </div>
</template>
<template>
    <div>
        <j-skeleton-image style="margin-top: 20px" active />
        <j-skeleton-title style="margin-top: 20px" active />
        <j-skeleton-paragraph style="margin-top: 20px" active />
        <j-skeleton-avatar style="margin-top: 20px" active />
        <j-skeleton-input style="margin-top: 20px; margin-left: 10px" active />
        <j-skeleton-image style="margin-top: 20px; margin-left: 10px" active />
        <j-skeleton-button style="margin-top: 20px; margin-left: 10px" active />
    </div>
</template>

自定义 Skeleton 组合

考虑到预设的 Skeleton 元素组合并不能满足所有场景,我们提供了插槽和属性支持在 Skeleton 组件下自定义布局和自由组合占位元素。

展开查看代码
vue
<template>
    <j-switch v-model:checked="loading" style="margin-bottom: 20px" @change="onChange" />

    <j-skeleton :loading="loading" active>
        <div>内容</div>

        <template #customNodes>
            <div style="flex: 1">
                <j-space>
                    <j-skeleton-avatar />
                    <j-skeleton-input />
                    <j-skeleton-button />
                </j-space>

                <div style="display: flex">
                    <j-skeleton-image style="margin-top: 20px" />
                    <div style="flex: 1; margin-left: 10px">
                        <j-skeleton-title style="margin-top: 20px" />
                        <j-skeleton-paragraph :rows="2" style="margin-top: 20px" />
                    </div>
                </div>
            </div>
        </template>
    </j-skeleton>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const loading = ref(true)

const refresh = () => {
    loading.value = true
    setTimeout(() => {
        loading.value = false
    }, 10000)
}

refresh()

const onChange = (value: boolean) => {
    if (value) {
        refresh()
    }
}
</script>
<template>
    <j-switch v-model:checked="loading" style="margin-bottom: 20px" @change="onChange" />

    <j-skeleton :loading="loading" active>
        <div>内容</div>

        <template #customNodes>
            <div style="flex: 1">
                <j-space>
                    <j-skeleton-avatar />
                    <j-skeleton-input />
                    <j-skeleton-button />
                </j-space>

                <div style="display: flex">
                    <j-skeleton-image style="margin-top: 20px" />
                    <div style="flex: 1; margin-left: 10px">
                        <j-skeleton-title style="margin-top: 20px" />
                        <j-skeleton-paragraph :rows="2" style="margin-top: 20px" />
                    </div>
                </div>
            </div>
        </template>
    </j-skeleton>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const loading = ref(true)

const refresh = () => {
    loading.value = true
    setTimeout(() => {
        loading.value = false
    }, 10000)
}

refresh()

const onChange = (value: boolean) => {
    if (value) {
        refresh()
    }
}
</script>

属性

参数说明类型默认值必填
loading值为true时,代表加载状态,展示骨架屏,否则直接展示子组件。boolean
active是否激活动画效果,如果开启,会对 Skeleton 下的其他占位组件生效,但不会覆盖各组件另行指定的 active 属性值。boolean
avatar头像配置boolean | SkeletonAvatarProps
paragraph段落配置boolean | SkeletonParagraphPropstrue
title标题配置boolean | SkeletonTitlePropstrue
customNodes自定义骨架屏元素VNode

SkeletonAvatarProps

参数说明类型默认值必填
active是否激活动画效果booleanundefined
shape头像的形状"circle" | "square"'circle'
size头像的尺寸number | "default" | "small" | "large"'default'

SkeletonButtonProps

参数说明类型默认值必填
active是否激活动画效果booleanundefined

SkeletonImageProps

参数说明类型默认值必填
active是否激活动画效果booleanundefined
wrapperSize图片占位容器的尺寸string | number
size图片内容的尺寸string | number
customImage自定义占位图VNode

SkeletonInputProps

参数说明类型默认值必填
active是否激活动画效果booleanundefined

SkeletonParagraphProps

参数说明类型默认值必填
active是否激活动画效果booleanundefined
rows段落占位行数number2
width段落占位的宽度配置,值为数组则对应每行的宽度,反之代表最后一行的宽度string | number | Array<string | number>

SkeletonTitleProps

参数说明类型默认值必填
active是否激活动画效果booleanundefined
width标题占位的宽度string | number'50%'