| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- <template>
- <view class="skeleton" :class="type">
- <view
- class="skeleton-line"
- v-for="i in lines"
- :key="i"
- :style="{ width: getLineLength(i), height: lineHeight }"
- ></view>
- </view>
- </template>
- <script setup lang="ts">
- interface Props {
- type?: 'default' | 'avatar' | 'card' | 'list';
- lines?: number;
- lineHeight?: string;
- }
- const props = withDefaults(defineProps<Props>(), {
- type: 'default',
- lines: 3,
- lineHeight: '24rpx'
- });
- const getLineLength = (index: number) => {
- if (props.type === 'list') {
- // 列表类型:长度递减
- const lengths = ['100%', '90%', '80%', '70%'];
- return lengths[(index - 1) % lengths.length];
- }
-
- if (props.type === 'card') {
- // 卡片类型:交替长度
- return index % 2 === 0 ? '100%' : '75%';
- }
-
- return '100%';
- };
- </script>
- <style lang="scss">
- .skeleton {
- width: 100%;
-
- &.avatar {
- display: flex;
- align-items: center;
- gap: $spacing-md;
-
- .skeleton-line:first-child {
- width: 80rpx !important;
- height: 80rpx !important;
- border-radius: $radius-circle;
- flex-shrink: 0;
- }
- }
-
- &.card {
- padding: $spacing-md;
- background: $color-bg-primary;
- border-radius: $radius-lg;
- }
-
- &-line {
- height: 24rpx;
- background: $color-bg-tertiary;
- border-radius: $radius-sm;
- margin-bottom: $spacing-sm;
- animation: skeleton 1.5s cubic-bezier(0.42, 0, 0.58, 1) infinite;
-
- &:last-child {
- margin-bottom: 0;
- }
- }
- }
- </style>
|