wd-grid-item.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <view :class="`wd-grid-item ${border && !gutter ? itemClass : ''} ${customClass}`" @click="click" :style="`${style};${customStyle}`">
  3. <view
  4. :class="`wd-grid-item__content ${square ? 'is-square' : ''} ${border && gutter > 0 ? 'is-round' : ''}`"
  5. :style="gutterContentStyle"
  6. :hover-class="hoverClass"
  7. >
  8. <slot>
  9. <view class="wd-grid-item__wrapper">
  10. <wd-badge v-bind="customBadgeProps">
  11. <slot name="icon">
  12. <wd-icon :name="icon" :size="iconSize" :custom-class="customIcon" />
  13. </slot>
  14. </wd-badge>
  15. </view>
  16. <slot name="text">
  17. <view :class="`wd-grid-item__text ${customText}`">{{ text }}</view>
  18. </slot>
  19. </slot>
  20. </view>
  21. </view>
  22. </template>
  23. <script lang="ts">
  24. export default {
  25. name: 'wd-grid-item',
  26. options: {
  27. virtualHost: true,
  28. addGlobalClass: true,
  29. styleIsolation: 'shared'
  30. }
  31. }
  32. </script>
  33. <script lang="ts" setup>
  34. import wdIcon from '../wd-icon/wd-icon.vue'
  35. import wdBadge from '../wd-badge/wd-badge.vue'
  36. import { onMounted, ref, watch, computed } from 'vue'
  37. import { useParent } from '../composables/useParent'
  38. import { GRID_KEY } from '../wd-grid/types'
  39. import { deepAssign, isDef, isUndefined, omitBy } from '../common/util'
  40. import { gridItemProps } from './types'
  41. import type { BadgeProps } from '../wd-badge/types'
  42. const props = defineProps(gridItemProps)
  43. const emit = defineEmits(['itemclick'])
  44. const style = ref<string>('')
  45. const gutterContentStyle = ref<string>('')
  46. const itemClass = ref<string>('')
  47. const gutter = ref<number>(0)
  48. const square = ref<boolean>(false)
  49. const border = ref<boolean>(true)
  50. const { parent: grid } = useParent(GRID_KEY)
  51. const childCount = computed(() => {
  52. if (isDef(grid) && isDef(grid.children)) {
  53. return grid.children.length
  54. } else {
  55. return 0
  56. }
  57. })
  58. const customBadgeProps = computed(() => {
  59. const badgeProps: Partial<BadgeProps> = deepAssign(
  60. isDef(props.badgeProps) ? omitBy(props.badgeProps, isUndefined) : {},
  61. omitBy(
  62. {
  63. max: props.max,
  64. isDot: props.isDot,
  65. modelValue: props.value,
  66. type: props.type
  67. },
  68. isUndefined
  69. )
  70. )
  71. return badgeProps
  72. })
  73. watch(
  74. () => childCount.value,
  75. () => {
  76. if (!grid) return
  77. const width = grid.props.column ? 100 / grid.props.column + '%' : 100 / (childCount.value || 1) + '%'
  78. // 单独定义间隔
  79. const gutterStyle = grid.props.gutter ? `padding:${grid.props.gutter}px ${grid.props.gutter}px 0 0; background-color: transparent;` : ''
  80. // 单独定义正方形
  81. const squareStyle = grid.props.square ? `background-color:transparent; padding-bottom: 0; padding-top:${width}` : ''
  82. style.value = `width: ${width}; ${squareStyle || gutterStyle}`
  83. },
  84. {
  85. deep: true,
  86. immediate: true
  87. }
  88. )
  89. onMounted(() => {
  90. init()
  91. })
  92. function init() {
  93. if (!grid) return
  94. const children = grid.children
  95. const width = grid.props.column ? 100 / grid.props.column + '%' : 100 / children.length + '%'
  96. // 单独定义间隔
  97. const gutterStyle = grid.props.gutter ? `padding:${grid.props.gutter}px ${grid.props.gutter}px 0 0; background-color: transparent;` : ''
  98. // 单独定义正方形
  99. const squareStyle = grid.props.square ? `background-color:transparent; padding-bottom: 0; padding-top:${width}` : ''
  100. // 间隔+正方形
  101. gutterContentStyle.value =
  102. grid.props.gutter && grid.props.square
  103. ? `right: ${grid.props.gutter}px; bottom:${grid.props.gutter}px;height: auto; background-color: ${grid.props.bgColor}`
  104. : `background-color: ${grid.props.bgColor}`
  105. border.value = Boolean(grid.props.border)
  106. square.value = Boolean(grid.props.square)
  107. gutter.value = Number(grid.props.gutter)
  108. style.value = `width: ${width}; ${squareStyle || gutterStyle}`
  109. }
  110. function click() {
  111. if (grid && !grid.props.clickable) return
  112. const { url, linkType } = props
  113. emit('itemclick')
  114. if (url) {
  115. switch (linkType) {
  116. case 'navigateTo':
  117. uni.navigateTo({
  118. url
  119. })
  120. break
  121. case 'reLaunch':
  122. uni.reLaunch({
  123. url
  124. })
  125. break
  126. case 'redirectTo':
  127. uni.redirectTo({
  128. url
  129. })
  130. break
  131. case 'switchTab':
  132. uni.switchTab({
  133. url
  134. })
  135. break
  136. default:
  137. console.error(`[wot-design] warning(wd-grid-item): linkType can not be ${linkType}`)
  138. break
  139. }
  140. }
  141. }
  142. /**
  143. * 设置样式
  144. * @param classes
  145. */
  146. function setiIemClass(classes: string) {
  147. itemClass.value = classes
  148. }
  149. const hoverClass = computed(() => {
  150. if (grid?.props.clickable) {
  151. return grid.props.hoverClass ? grid.props.hoverClass : 'wd-grid-item__content--hover'
  152. }
  153. return 'none'
  154. })
  155. defineExpose({
  156. setiIemClass,
  157. itemClass,
  158. init
  159. })
  160. </script>
  161. <style lang="scss" scoped>
  162. @import './index.scss';
  163. </style>