wd-tooltip.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <template>
  2. <view :class="`wd-tooltip ${customClass}`" :style="customStyle" id="tooltip" @click.stop="popover.noop">
  3. <!-- 用于为渲染获取宽高的元素 -->
  4. <view class="wd-tooltip__pos wd-tooltip__hidden" id="pos">
  5. <view class="wd-tooltip__container custom-pop">
  6. <view v-if="!useContentSlot" class="wd-tooltip__inner">{{ content }}</view>
  7. </view>
  8. </view>
  9. <wd-transition custom-class="wd-tooltip__pos" :custom-style="popover.popStyle.value" :show="showTooltip" name="fade" :duration="200">
  10. <view class="wd-tooltip__container custom-pop">
  11. <view v-if="visibleArrow" :class="`wd-tooltip__arrow ${popover.arrowClass.value} ${customArrow}`" :style="popover.arrowStyle.value"></view>
  12. <!-- 普通模式 -->
  13. <view v-if="!useContentSlot" class="wd-tooltip__inner">{{ content }}</view>
  14. <!-- 用户自定义样式 -->
  15. <slot name="content" v-else />
  16. </view>
  17. <wd-icon v-if="showClose" name="close" custom-class="wd-tooltip__close-icon" @click="toggle"></wd-icon>
  18. </wd-transition>
  19. <view @click="toggle" class="wd-tooltip__target" id="target">
  20. <slot />
  21. </view>
  22. </view>
  23. </template>
  24. <script lang="ts">
  25. export default {
  26. name: 'wd-tooltip',
  27. options: {
  28. addGlobalClass: true,
  29. virtualHost: true,
  30. styleIsolation: 'shared'
  31. }
  32. }
  33. </script>
  34. <script lang="ts" setup>
  35. import wdIcon from '../wd-icon/wd-icon.vue'
  36. import wdTransition from '../wd-transition/wd-transition.vue'
  37. import { getCurrentInstance, inject, onBeforeMount, onBeforeUnmount, onMounted, ref, watch } from 'vue'
  38. import { usePopover } from '../composables/usePopover'
  39. import { closeOther, pushToQueue, removeFromQueue } from '../common/clickoutside'
  40. import { type Queue, queueKey } from '../composables/useQueue'
  41. import { tooltipProps, type TooltipExpose } from './types'
  42. const props = defineProps(tooltipProps)
  43. const emit = defineEmits(['update:modelValue', 'menuclick', 'change', 'open', 'close'])
  44. const popover = usePopover(props.visibleArrow)
  45. const queue = inject<Queue | null>(queueKey, null)
  46. const selector: string = 'tooltip'
  47. const { proxy } = getCurrentInstance() as any
  48. const showTooltip = ref<boolean>(false) // 控制tooltip显隐
  49. watch(
  50. () => props.content,
  51. (newVal) => {
  52. if (newVal === null || newVal === undefined) {
  53. // eslint-disable-next-line prettier/prettier
  54. console.error('[wot-design] warning(wd-tooltip): content can\'t be null or undefined')
  55. }
  56. }
  57. )
  58. watch(
  59. () => props.placement,
  60. () => {
  61. popover.init(props.placement, props.visibleArrow, selector)
  62. }
  63. )
  64. watch(
  65. () => props.modelValue,
  66. (newValue) => {
  67. showTooltip.value = newValue
  68. }
  69. )
  70. watch(
  71. () => showTooltip.value,
  72. (newValue) => {
  73. if (newValue) {
  74. popover.control(props.placement, props.offset)
  75. if (queue && queue.closeOther) {
  76. queue.closeOther(proxy)
  77. } else {
  78. closeOther(proxy)
  79. }
  80. }
  81. popover.showStyle.value = newValue ? 'display: inline-block;' : 'display: none;'
  82. emit('change', { show: newValue })
  83. emit(`${newValue ? 'open' : 'close'}`)
  84. }
  85. )
  86. onMounted(() => {
  87. popover.init(props.placement, props.visibleArrow, selector)
  88. })
  89. onBeforeMount(() => {
  90. if (queue && queue.pushToQueue) {
  91. queue.pushToQueue(proxy)
  92. } else {
  93. pushToQueue(proxy)
  94. }
  95. popover.showStyle.value = props.modelValue ? 'opacity: 1;' : 'opacity: 0;'
  96. })
  97. onBeforeUnmount(() => {
  98. if (queue && queue.removeFromQueue) {
  99. queue.removeFromQueue(proxy)
  100. } else {
  101. removeFromQueue(proxy)
  102. }
  103. })
  104. function toggle() {
  105. if (props.disabled) return
  106. updateModelValue(!showTooltip.value)
  107. }
  108. function open() {
  109. updateModelValue(true)
  110. }
  111. function close() {
  112. updateModelValue(false)
  113. }
  114. function updateModelValue(value: boolean) {
  115. showTooltip.value = value
  116. emit('update:modelValue', value)
  117. }
  118. defineExpose<TooltipExpose>({
  119. open,
  120. close
  121. })
  122. </script>
  123. <style lang="scss" scoped>
  124. @import './index.scss';
  125. </style>