slot/slot_auto_ellipsis_text.vue 表格内文字自适应宽度溢出... 带tip vue2 "view-design": "4.6.1"

slot/slot_auto_ellipsis_text.vue 表格内文字自适应宽度溢出... 带tip vue2 "view-design": "4.6.1"

slot_auto_ellipsis_text.vue

<template>
  <div class="auto-ellipsis-text"
       @mouseenter="handleMouseEnter"
       @mouseleave="handleMouseLeave">
    <Tooltip :disabled="!showTooltip"
             placement="top"
             transfer
             :max-width="tipMaxWidth"
             theme="light"
             transferClassName="tf-tooltip">
      <!-- 自定义 tip 内容 -->
      <div slot="content"
           :style="`max-height:${tipMaxHeight}px;overflow-y:auto;padding:3px;`">{{ tooltipContent }}</div>

      <div ref="textContainer"
           class="text-container">
        <span ref="textContent"
              class="text-content">
          <slot>{{ text }}</slot>
        </span>
      </div>
    </Tooltip>
  </div>
</template>

<script>
import { Tooltip } from 'view-design'

export default {
  name: 'AutoEllipsisText',
  components: {
    Tooltip,
  },
  props: {
    text: {
      type: String,
      default: '',
    },
    tipMaxHeight: {
      type: Number,
      default: 150,
    },
    tipMaxWidth: {
      type: Number,
      default: 450,
    },
  },
  data () {
    return {
      showTooltip: false,
      tooltipContent: '',
    }
  },
  methods: {
    getFullText () {
      if (this.$slots.default) {
        const slotText = this.$slots.default
          .map((vnode) => vnode.text || '')
          .join('')
          .trim()
        if (slotText) return slotText
      }
      return (this.text || '').trim()
    },
    handleMouseEnter () {
      const container = this.$refs.textContainer
      const content = this.$refs.textContent
      if (!container || !content) return

      // 用 Range 测量文本实际宽度(不受 inline / overflow 影响)
      const range = document.createRange()
      range.selectNodeContents(content)
      const textWidth = range.getBoundingClientRect().width
      const containerWidth = container.getBoundingClientRect().width

      const isOverflow = textWidth > containerWidth

      // console.info('textWidth', textWidth)
      // console.info('containerWidth', containerWidth)
      // console.info('isOverflow', isOverflow)

      if (isOverflow) {
        this.tooltipContent = this.getFullText()
        this.showTooltip = true
      } else {
        this.showTooltip = false
        this.tooltipContent = ''
      }
    },
    handleMouseLeave () {
      // console.info('handleMouseLeave')
      // 离开时重置,下次进入重新判断
      // this.showTooltip = false
      // this.tooltipContent = ''
    },
  },
}
</script>

<style scoped>
.auto-ellipsis-text {
  display: block;
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.auto-ellipsis-text ::v-deep .ivu-tooltip {
  display: block;
  width: 100%;
  max-width: 100%;
}

.auto-ellipsis-text ::v-deep .ivu-tooltip-rel {
  display: block;
  width: 100%;
  max-width: 100%;
  min-width: 0;
}

.text-container {
  display: block;
  width: 100%;
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  cursor: default;
}

.text-content {
  display: inline;
  white-space: nowrap;
}
</style>

使用方法

<slot_auto_ellipsis_text :text="String(row[item.keyName])" />
posted @ 2026-10-09 11:51  彭成刚  阅读(11)  评论(0)    收藏  举报