wd-skeleton.vue 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. <!--
  2. * @Author: weisheng
  3. * @Date: 2024-03-15 11:36:12
  4. * @LastEditTime: 2024-04-01 20:24:22
  5. * @LastEditors: weisheng
  6. * @Description:
  7. * @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-skeleton/wd-skeleton.vue
  8. * 记得注释
  9. -->
  10. <template>
  11. <view :class="`wd-skeleton ${customClass}`" :style="customStyle">
  12. <view class="wd-skeleton__content" v-if="show">
  13. <view class="wd-skeleton__row" v-for="(row, index) of parsedRowCols" :key="`row-${index}`">
  14. <view v-for="(col, idx) of row" :key="`col-${idx}`" :class="col.class" :style="col.style" />
  15. </view>
  16. </view>
  17. <view v-else>
  18. <slot />
  19. </view>
  20. </view>
  21. </template>
  22. <script lang="ts">
  23. export default {
  24. // #ifdef H5
  25. name: 'wd-skeleton',
  26. // #endif
  27. options: { virtualHost: true, addGlobalClass: true, styleIsolation: 'shared' }
  28. }
  29. </script>
  30. <script lang="ts" setup>
  31. import type { CSSProperties } from 'vue'
  32. import { ref, computed, watch } from 'vue'
  33. import type { SkeletonRowCol, SkeletonRowColObj } from './types'
  34. import { skeletonProps } from './types'
  35. import { isNumber, addUnit } from '../common/util'
  36. const themeMap = {
  37. avatar: [{ type: 'circle', height: '64px', width: '64px' }],
  38. image: [{ type: 'rect', height: '64px', width: '64px' }],
  39. text: [
  40. 1,
  41. [
  42. { width: '24%', height: '16px', marginRight: '16px' },
  43. { width: '76%', height: '16px' }
  44. ]
  45. ],
  46. paragraph: [1, 1, 1, { width: '55%' }]
  47. }
  48. const props = defineProps(skeletonProps)
  49. const rowCols = ref<SkeletonRowCol[]>([])
  50. const parsedRowCols = computed(() => {
  51. return rowCols.value.map((item) => {
  52. if (isNumber(item)) {
  53. return [
  54. {
  55. class: getColItemClass({ type: 'text' }),
  56. style: {}
  57. }
  58. ]
  59. }
  60. if (Array.isArray(item)) {
  61. return item.map((col) => {
  62. return {
  63. ...col,
  64. class: getColItemClass(col),
  65. style: getColItemStyle(col)
  66. }
  67. })
  68. }
  69. const nItem = item as SkeletonRowColObj
  70. return [
  71. {
  72. ...nItem,
  73. class: getColItemClass(nItem),
  74. style: getColItemStyle(nItem)
  75. }
  76. ]
  77. })
  78. })
  79. function getColItemClass(rowCol: SkeletonRowColObj) {
  80. return ['wd-skeleton__col', `wd-skeleton--type-${rowCol.type || 'text'}`, { [`wd-skeleton--animation-${props.animation}`]: props.animation }]
  81. }
  82. function getColItemStyle(rowCol: SkeletonRowColObj) {
  83. const style: CSSProperties = {}
  84. const styleName = ['size', 'width', 'height', 'margin', 'background', 'marginLeft', 'marginRight', 'borderRadius', 'backgroundColor']
  85. for (const name of styleName) {
  86. if (Object.prototype.hasOwnProperty.call(rowCol, name)) {
  87. const px = addUnit(rowCol[name])
  88. if (name === 'size') {
  89. style.width = px
  90. style.height = px
  91. } else {
  92. ;(style as any)[name] = px
  93. }
  94. }
  95. }
  96. return style
  97. }
  98. watch(
  99. () => props.rowCol,
  100. (rowCol) => {
  101. rowCols.value = [...(Array.isArray(rowCol) && rowCol.length ? props.rowCol : themeMap[props.theme])]
  102. },
  103. { immediate: true }
  104. )
  105. const show = computed(() => props.loading == undefined || props.loading === true)
  106. </script>
  107. <style lang="scss" scoped>
  108. @import './index.scss';
  109. </style>