组件开发--文本自适应溢出隐藏,tooltip查看

288 阅读1分钟

2024.3.23

需求: 文本溢出隐藏,并且hover上后可查看全部文本内容。

问题: 起初根据文本的长度来判断是否溢出隐藏,但是这样不能自适应,文本不长的,没有出现省略号,也会显示tooltip。

解决: 模拟 el-table show-overflow-tooltip 原理,写一个自定义组件,

<!--
 * @Author: SunnyYang
 * @Date: 2024-03-22 11:05:56
 * @LastEditors: SunnyYang
 * @LastEditTime: 2024-03-23 17:37:17
 * @Description: 
-->
<template>
  <el-tooltip :disabled="disabled" :content="content" :placement="placement" effect="dark" raw-content>
    <div :id="id" class="overflow-tooltip">
      <slot />
    </div>
  </el-tooltip>
</template>

<script setup name="OverflowTooltip">
import { onMounted, ref } from 'vue'
const props = defineProps({
  content: [String, Number, Boolean],
  placement: {
    type: String,
    default: 'top-start',
  },
})

const id = ref(Math.random().toString(36).slice(2)),
  disabled = ref(true),
  title = ref('')

onMounted(() => {
  //获取ID元素
  const el = document.getElementById(id.value)
  // 获取元素的样式( CSSStyleDeclaration 对象)
  const elComputed = document.defaultView.getComputedStyle(el, '')
  // 获取元素的 padding 值
  const padding =
    parseInt(elComputed.paddingLeft.replace('px', '')) + parseInt(elComputed.paddingRight.replace('px', ''))
  // 创建一个 Range 对象:使用 range 代替 scrollWidth 来判断文本是否溢出,这样做是为了解决潜在的 bug。
  const range = document.createRange()
  // 设置 range 的起点
  range.setStart(el, 0)
  // 设置 range 的终点,因为起终点都在同一个节点上,所以设置终点偏移量以选中节点的内容
  range.setEnd(el, el.childNodes.length)
  // 获取节点的内容的宽度
  const rangeWidth = range.getBoundingClientRect().width
  //设置el下的第一个子节点溢出隐藏
  if (el.firstElementChild) el.firstElementChild.classList.add('text-ellipsis')

  // 节点的内容真实宽度大于节点宽度时设置disabled为false,启用tooltip
  // 由于element ui 中把 box-sizing 设置为了 border-box,因此真实宽度需要加上padding

  if (rangeWidth + padding > el.offsetWidth || el.scrollWidth > el.offsetWidth) {
    disabled.value = false
    title.value = props.content
  }
})
</script>

<style lang="scss" scoped>
.text-ellipsis {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.overflow-tooltip {
  @extend .text-ellipsis;
  min-width: 50px;
  box-sizing: border-box;
  display: flex;
}
</style>

引用组件:

注意:OverflowTooltip组件传递的插槽内容要有一层span标签包裹

<OverflowTooltip :content="tableItem.flowName">
   <span> {{ tableItem.flowName }}</span>
</OverflowTooltip>
<OverflowTooltip :content="`<strong>ID:</strong>${tableItem.flowCode}`" placement="bottom-start">
   <span class="idName">ID:{{ tableItem.flowCode }}</span>
</OverflowTooltip>

出现如下问题,要把<el-tooltip放置在最外层

参考链接