组件 newTooltipText.vue
<template>
<el-tooltip
effect="dark"
:placement="placement"
:enterable="true"
:show-after="200"
:offset="10"
:popper-class="props.textTooltipPopperClass"
:popper-style="props.popperStyle"
:content="props.content"
:disabled="disabledTooltip"
>
<slot :mouseoverSelf="handleHover"></slot>
</el-tooltip>
</template>
<script lang="ts" setup>
import { ref } from "vue"
const props = defineProps({
content: {
type: String,
default: ""
},
line: {
type: Number,
default: 1
},
textTooltipPopperClass: {
type: String,
default: ""
},
popperStyle: {
type: String,
default: ""
},
placement: {
type: String,
default: "top"
}
})
function handleHover(event: MouseEvent) {
disabledTooltip.value = !isTextEllipsis(event.target as HTMLElement)
}
function setPrecision(num, Places) {
if (!num) {
return 0
}
let backwardLead: any = "1"
for (let i = 0; i < Places; i++) {
backwardLead += "0"
}
return Math.floor(num * +backwardLead) / backwardLead
}
const getPadding = (el: HTMLElement) => {
const style = window.getComputedStyle(el, null)
const paddingLeft = Number.parseInt(style.paddingLeft, 10) || 0
const paddingRight = Number.parseInt(style.paddingRight, 10) || 0
const paddingTop = Number.parseInt(style.paddingTop, 10) || 0
const paddingBottom = Number.parseInt(style.paddingBottom, 10) || 0
return {
left: paddingLeft,
right: paddingRight,
top: paddingTop,
bottom: paddingBottom
}
}
const isTextEllipsis = (el: HTMLElement) => {
const range = document.createRange()
range.setStart(el, 0)
range.setEnd(el, el.childNodes.length)
let rangeWidth = range.getBoundingClientRect().width
let rangeHeight = range.getBoundingClientRect().height
const offsetWidth = rangeWidth - Math.floor(rangeWidth)
const { width: cellChildWidth, height: cellChildHeight } = el.getBoundingClientRect()
if (offsetWidth < 0.001) {
rangeWidth = Math.floor(rangeWidth)
}
const offsetHeight = rangeHeight - Math.floor(rangeHeight)
if (offsetHeight < 0.001) {
rangeHeight = Math.floor(rangeHeight)
}
const { top, left, right, bottom } = getPadding(el)
const horizontalPadding = left + right
const verticalPadding = top + bottom
if (props.line === 1) {
// 单行省略判断
console.log(
"rangeWidth + horizontalPadding > cellChildWidth",
rangeWidth + horizontalPadding > cellChildWidth
)
console.log(
"rangeHeight + verticalPadding > cellChildHeight",
rangeHeight + verticalPadding > cellChildHeight
)
console.log("el.scrollWidth > el.clientWidth", el.scrollWidth > el.clientWidth)
console.log("rangeWidth, horizontalPadding ", rangeWidth, horizontalPadding)
console.log("rangeHeight, verticalPadding", rangeHeight, verticalPadding)
console.log("cellChildWidth", cellChildWidth)
console.log("cellChildHeight", cellChildHeight)
console.log("el.scrollWidth", el.scrollWidth)
console.log("el.clientWidth", el.clientWidth)
return (
setPrecision(rangeWidth + horizontalPadding, 2) > setPrecision(cellChildWidth, 2) ||
rangeHeight + verticalPadding > cellChildHeight ||
el.scrollWidth > el.clientWidth
)
} else {
// 多行省略判断
return el.scrollHeight > el.clientHeight
}
}
const disabledTooltip = ref(true)
</script>
使用
多行
注意:需要换行
<newTooltipText
content="xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
:line="2"
textTooltipPopperClass="table_tooltip"
v-slot="slotProps"
>
<span
class="line_ellipsis_2"
@mouseover.self="slotProps.mouseoverSelf"
>xxxxxxxxxxxxxxxxxxxxxxxxxxxx</span
>
</newTooltipText>
.line_ellipsis_2 {
line-height: 24px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.table_tooltip {
max-width: 300px;
white-space: pre-wrap;
}
单行
注意:包裹的父级一定有实际的width
<newTooltipText
:content="xxxxxxxxxxxxxxxxxxxxxx"
:line="1"
textTooltipPopperClass="table_tooltip"
v-slot="slotProps"
>
<span class="line_ellipsis_1" @mouseover.self="slotProps.mouseoverSelf">xxxxxxxxxxxxxxxxxxxxxx</span>
</newTooltipText>
.line_ellipsis_1 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}