目的是为了当el-table的一个单元格展示多行的内容,又使用了文字的省略,需要区分出文字不多不被省略的单元格不展示tooltip,文字很多被省略的展示tooltip
原理是使用自定义指令
首先创建类,用于文字的省略,超出的文字会以……的形式展示
.text-ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
在el-table中使用自定义指令v-hiddeTooltip,原理是使用el-tooltip包裹单元格,不要使用show-overflow-tooltip,通过el-tooltip的插槽展示多行的内容,通过自定义指令判断什么情况下禁用el-tooltip
<el-table-column label="信息很多" prop="points" min-width="170">
<template #default="{ row }">
<el-tooltip :disabled="!row.hiddeTooltip" placement="top">
<template #content>
<div class="column-left">
<span>世有伯乐,然后有千里马。世有伯乐,然后有千里马。</span>
<span>世有伯乐,然后有千里马。世有伯乐,然后有千里马。</span>
<span>世有伯乐,然后有千里马。世有伯乐,然后有千里马。</span>
</div>
</template>
<div v-hiddeTooltip="row" class="column-left">
<span class="text-ellipsis">世有伯乐,然后有千里马。世有伯乐,然后有千里马。</span>
<span class="text-ellipsis">世有伯乐,然后有千里马。世有伯乐,然后有千里马。</span>
<span class="text-ellipsis">世有伯乐,然后有千里马。世有伯乐,然后有千里马。</span>
</div>
</el-tooltip>
</template>
</el-table-column>
自定义指令v-hiddeTooltip的内容为
import type { App } from 'vue'
// 来自element源码
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
}
}
export function hiddeTooltip(app: App) {
app.directive('hiddeTooltip', {
mounted(el, binding) {
const list = el.querySelectorAll('.text-ellipsis') as Array<HTMLElement>
let flag = false
for (let index = 0; index < list.length; index++) {
const cellChild = list[index]
// 来自element源码
const range = document.createRange()
range.setStart(cellChild, 0)
range.setEnd(cellChild, cellChild.childNodes.length)
let rangeWidth = range.getBoundingClientRect().width
let rangeHeight = range.getBoundingClientRect().height
const offsetWidth = rangeWidth - Math.floor(rangeWidth)
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(cellChild)
const horizontalPadding = left + right
const verticalPadding = top + bottom
// 判断也是来自源码
if (
rangeWidth + horizontalPadding > cellChild.offsetWidth ||
rangeHeight + verticalPadding > cellChild.offsetHeight ||
cellChild.scrollWidth > cellChild.offsetWidth
) {
flag = true
}
}
// 只要最后是个true
if (flag) {
binding.value.hiddeTooltip = true
}
}
})
}
自定义指令代码的原理是,验证自定义指令绑定的单元格下的每一个的有text-ellipsis的元素是否符合已经被省略的条件,只要有一个被省略的,flag即为true,反哺出去,把表格中绑定位置的单元格位置的hiddeTooltip属性赋值为true,之后通过hiddeTooltip属性去判断外部包围的el-tooltiip是否Disabled禁用。
是否符合已经被省略的条件的源码来自element-plus的源码,可以下载源码,直接搜索 // 判断是否text-overflow, 如果是就显示tooltip 找到events-helper.ts就能看到源码了