<template> <!-- 骨架屏--> <view> <view v-if="loading" class="skeleton" :class="{ animate: animate }" :style="{ justifyContent: flexType }"> <!-- 轮播图 --> <view v-if="imgTitle" class="skeleton-imgTitle" style="width: 95%;border-radius: 10px;height: 100px;display: block;"></view> <!-- 头像图 --> <view v-if="showAvatar && !imgTitle" class="skeleton-avatar" v-for="(item, index) in nameRow" :key="index" :class="[avatarShape]" :style="{ width: avatarSize, height: avatarSize }" ></view> <!-- 文字条 --> <view class="skeleton-content" v-if="showTitle && !imgTitle"> <view class="skeleton-title" :style="{ width: titleWidth }"></view> <view class="skeleton-rows"><view class="skeleton-row-item" v-for="(item, index) in rowList" :key="index" :style="{ width: item.width }"></view></view> </view> </view> <view v-else><slot></slot></view> <view class="NavBar clearfix"> <view class="nav-li" v-for="(item, index) in 8" :key="index"><view class="nav-icon"></view></view> </view> <view class="magic-adv-view"></view> <view class="seckill-view"> <view class="seckill-top"></view> <view class="seckill-goods-view"> <view class="seckill-goods" style="margin-right: 20upx;" ></view> <view class="seckill-goods"></view> </view> </view> </view> </template> <script> const DEFAULT_ROW_WIDTH = '100%'; const DEFAULT_LAST_ROW_WIDTH = '60%'; export default { name: "Skeleton", props: { loading: { type: Boolean, default: true }, imgTitle: { type: Boolean, default: false }, nameRow: { type: Number, default: 1 }, flexType: { type: String, default: 'flex-start' // center 居中 √ space-between 两端对齐 √ space-around 子元素拉手分布 √ flex-start 居左 flex-end 居右 }, showAvatar: { type: Boolean, default: true }, avatarSize: { type: String, default: '50px' }, avatarShape: { type: String, default: 'round' // square | round }, showTitle: { type: Boolean, default: false }, titleWidth: { type: String, default: '40%' }, row: { type: Number, default: 3 }, animate: { type: Boolean, default: true } }, data() { return {}; }, computed: { rowList() { let list = []; for (let i = 0; i < this.row; i++) { list.push({ width: i === this.row - 1 && i !== 0 ? DEFAULT_LAST_ROW_WIDTH : DEFAULT_ROW_WIDTH }); } return list; } } }; </script> <style scoped lang="scss"> .seckill-view { width: 680upx; margin: 0 auto; .seckill-top { height: 70upx; background-color: #f5f5f5; margin-bottom: 30upx; } .seckill-goods-view { .seckill-goods { display: inline-block; width: 330upx; height: 300upx; background-color: #f5f5f5; } } } .magic-adv-view { width: 680upx; height: 200upx; background-color: #f5f5f5; margin: 20upx auto; } .NavBar { background: #fff; padding-top: 40upx; display: -webkit-flex; display: flex; width: 100%; justify-content: space-between; flex-wrap: wrap; } .nav-icon { width: 88upx; height: 88upx; margin: 0 auto; display: block; background-color: #f5f5f5; padding-bottom: 10upx; } .nav-li { width: 25%; font-size: 26upx; text-align: center; margin-bottom: 40upx; } .skeleton { display: flex; margin: 16px; --bg-color: #f2f3f5; --row-height: 16px; --row-margin-top: 16px; } .skeleton-imgTitle { flex-wrap: wrap; background: var(--bg-color); margin: 10px auto; } .skeleton-avatar { flex-shrink: 0; background: var(--bg-color); margin-right: 8px; } .skeleton-avatar.round { border-radius: 50%; } .skeleton-content { width: 100%; } .skeleton-title { background-color: var(--bg-color); height: var(--row-height); } .skeleton-title + .skeleton-rows { margin-top: var(--row-margin-top); } .skeleton-rows { } .skeleton-row-item { background-color: var(--bg-color); height: var(--row-height); } .skeleton-row-item:not(:first-child) { margin-top: var(--row-margin-top); } .skeleton.animate { animation: skeleton-blink 1.2s ease-in-out infinite; } @keyframes skeleton-blink { 0% { opacity: 1; } 50% { opacity: 0.6; } 100% { opacity: 1; } } </style>