index.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <div
  3. class="skeleton space-y"
  4. :class="{ animated: animate }"
  5. :style="`--color:${bgColor}`"
  6. v-if="loading"
  7. >
  8. <div
  9. class="skeleton-row space-x"
  10. :class="[styleMaps[item.align || 'left'], styleMaps[item.verticalAlign || 'middle']]"
  11. v-for="(item, index) in rowList"
  12. :style="item.style || {}"
  13. :key="index"
  14. >
  15. <div
  16. class="skeleton-row-item space-y"
  17. v-for="(item1, index1) in item.colItems"
  18. :class="[item1.shape || '', item1.childRowItems ? 'no-height' : '']"
  19. :key="index1"
  20. :style="item1.style || { width: `${100 / item.colItems}%` }"
  21. >
  22. <template v-if="item1.childRowItems">
  23. <div
  24. class="skeleton-col-item"
  25. v-for="(item2, index2) in item1.childRowItems"
  26. :class="item2.shape || ''"
  27. :key="index2"
  28. :style="item2.style || {}"
  29. ></div>
  30. </template>
  31. </div>
  32. </div>
  33. </div>
  34. <div v-else><slot></slot></div>
  35. </template>
  36. <script>
  37. export default {
  38. name: 'Skeleton',
  39. props: {
  40. bgColor: {
  41. type: String,
  42. default: '#f1f1f1',
  43. },
  44. rowList: {
  45. type: Array,
  46. default: () => config.common.skeletons,
  47. },
  48. loading: {
  49. type: Boolean,
  50. default: true,
  51. },
  52. animate: {
  53. type: Boolean,
  54. default: true,
  55. },
  56. scale: {
  57. type: String,
  58. },
  59. },
  60. data() {
  61. return {
  62. styleMaps: {
  63. left: 'justify-start',
  64. center: 'justify-center',
  65. right: 'justify-end',
  66. between: 'justify-between',
  67. around: 'justify-around',
  68. top: 'items-start',
  69. middle: 'items-center',
  70. bottom: 'items-end',
  71. },
  72. }
  73. },
  74. }
  75. </script>
  76. <style lang="scss" scoped>
  77. .skeleton {
  78. width: 100%;
  79. &.animated {
  80. animation: blink 1.2s ease-in-out infinite;
  81. }
  82. & div {
  83. box-sizing: border-box;
  84. }
  85. }
  86. .skeleton-row {
  87. display: flex;
  88. align-content: space-between;
  89. width: 100%;
  90. }
  91. .skeleton-row-item,
  92. .skeleton-col-item {
  93. // display: inline-block;
  94. height: $p-spac * 2;
  95. border-radius: 6rpx;
  96. &:not(.no-height) {
  97. background: var(--color);
  98. }
  99. &.round {
  100. border-radius: 999px;
  101. }
  102. &.circle {
  103. border-radius: 50%;
  104. }
  105. &.no-height {
  106. height: auto;
  107. }
  108. }
  109. .skeleton-col-item:last-child {
  110. margin: 0;
  111. }
  112. .space-x > div,
  113. .space-x > view {
  114. --tw-space-x-reverse: 0;
  115. margin-right: calc($p-spacd2 * var(--tw-space-x-reverse));
  116. margin-left: calc($p-spacd2 * calc(1 - var(--tw-space-x-reverse)));
  117. &:first-child {
  118. margin: 0;
  119. }
  120. }
  121. .space-y > div,
  122. .space-y > view {
  123. --tw-space-y-reverse: 0;
  124. margin-top: calc($p-spacd2 * var(--tw-space-y-reverse));
  125. margin-bottom: calc($p-spacd2 * calc(1 - var(--tw-space-y-reverse)));
  126. }
  127. .justify-start {
  128. justify-content: flex-start;
  129. }
  130. .justify-end {
  131. justify-content: flex-end;
  132. }
  133. .justify-center {
  134. justify-content: center;
  135. }
  136. .justify-between {
  137. justify-content: space-between;
  138. }
  139. .justify-around {
  140. justify-content: space-around;
  141. }
  142. .items-start {
  143. align-items: flex-start;
  144. }
  145. .items-end {
  146. align-items: flex-end;
  147. }
  148. .items-center {
  149. align-items: center;
  150. }
  151. @keyframes blink {
  152. 0% {
  153. opacity: 1;
  154. }
  155. 50% {
  156. opacity: 0.6;
  157. }
  158. 100% {
  159. opacity: 1;
  160. }
  161. }
  162. </style>