问题描述(show-overflow-tooltip)
- 表格某一列内容超长时,鼠标悬浮时会闪烁抖动,显示不出悬浮弹框
问题原因分析:
-
showOverflowTooltip执行了td鼠标移入mouseenter、鼠标移出mouseleave方法
-
通过控制台,可以看到,当鼠标移入时,会不停的打印移入移出,其实我就移入了一次
- 原因是当鼠标移入时,本来已经显示了弹框,但是由于内容超长,弹框内容撑开鼠标又被移出了,触发了移出方法,就隐藏了弹框,这个过程很短暂,以至于看不到
- 由于el-table列td的mouseenter、mouseleave方法都没有设置延迟,所以很容易在触发移入的时候也触发了移出
解决思路:
- td的mouseenter设置延迟200ms再显示tooltip弹框,修改handleCellMouseEnter方法
if (
(rangeWidth + padding > cellChild.offsetWidth ||
cellChild.scrollWidth > cellChild.offsetWidth) &&
this.$refs.tooltip
) {
const tooltip = this.$refs.tooltip
setTimeout(() => {
if (tooltip.showPopper) {
return
}
// TODO 会引起整个 Table 的重新渲染,需要优化
...
}, 201)
}
- td的mouseleave设置延迟200ms再关闭tooltip弹框,修改handleCellMouseLeave方法
if (tooltip) {
//tooltip.setExpectedState(false)
//tooltip.handleClosePopper()
// hide方法调用了setExpectedState(false)、debounceClose方法,debounceClose带有200ms的抖动延迟再执行handleClosePopper
tooltip.hide()
}
- 其他方式:el-popover代替 show-overflow-tooltip
- 其他方式:重写el-tooltip,代替show-overflow-tooltip,思路是鼠标移入时计算内容宽度和当前元素宽度,如果满足: 内容真实渲染宽度>元素的实际宽度或者实际内容的宽度(包括由于溢出而无法展示在网页的不可见部分)>元素的实际宽度,就显示tooltip,不满足就禁用tooltip
<template>
<el-tooltip
class="item"
effect="dark"
placement="top-start"
:disabled="!isShowTooltip"
>
<div
slot="content"
class="common-custom-tooltips"
v-html="hoverTitle"
></div>
<span
:id="id"
class="overflow-tooltip"
@mouseenter="onMouseOver"
v-html="content"
></span>
</el-tooltip>
</template>
<script>
export default {
name: 'OverflowTooltip',
props: {
content: [String, Number, Boolean],
title: [String, Number, Boolean]
},
data() {
return {
hoverTitle: '',
id: Math.random().toString(36).slice(2),
isShowTooltip: false
}
},
methods: {
onMouseOver() {
const el = document.getElementById(this.id)
const elComputed = document.defaultView.getComputedStyle(el, '')
const padding =
parseInt(elComputed.paddingLeft.replace('px', '')) +
parseInt(elComputed.paddingRight.replace('px', ''))
const range = document.createRange()
range.setStart(el, 0)
range.setEnd(el, el.childNodes.length)
const rangeWidth = range.getBoundingClientRect().width
this.isShowTooltip =
rangeWidth + padding > el.offsetWidth || el.scrollWidth > el.offsetWidth
if (this.isShowTooltip) {
this.hoverTitle = this.title || this.content
}
}
}
}
</script>
<style scoped>
.overflow-tooltip {
display: inline-block;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
}
</style>
找到原因了,就能从根本解决问题,element没有考虑到超长内容的情况,也算是他们的一个bug吧