知识点:scrollWidth 和 Range
1、scrollWidth
scrollWidth: 只读属性, 表示的是节点中的内容宽度,包括由于 overflow 溢出而在屏幕上不可见的内容。
2、Range
调用 Document.createRange() 可以生成一个 Range 对象。一旦一个 Range 对象被建立,在使用它的大多数方法之前需要去设置它的临界点。
vue3完整代码
<template>
<div class="overflow-box-wrapper" :style="{width: width}">
<div
ref="overflowBoxRef"
class="overflow-box"
@mouseenter="onMouseenter"
@mouseleave="onMouseleave"
>
{{ content }}
</div>
<div class="tips" v-if="isShowTips">{{ content }}</div>
</div>
</template>
<script setup>
import { onMounted, ref, defineProps } from "vue"
defineProps({
content: {
type: [String, Number]
},
width: {
type: String
}
})
const isShowTips = ref(false)
const overflowBoxRef = ref(null)
const checkOverflowHidden = (el) => {
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;
if ( rangeWidth + padding > el.offsetWidth || el.scrollWidth > el.offsetWidth ) {
return true
}
return false
}
const onMouseenter = () => {
const isOverflowHidden = checkOverflowHidden(overflowBoxRef.value)
if (isOverflowHidden) {
isShowTips.value = true
}
}
const onMouseleave = () => {
isShowTips.value = false
}
</script>
<style lang="scss" scoped>
.overflow-box-wrapper {
position: relative;
}
.overflow-box {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.tips {
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%, -100%);
white-space: nowrap;
border: 1px solid #333;
padding: 4px 10px;
border-radius: 4px;
line-height: 1;
&::after {
display: block;
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%,100%);
width: 0;
height: 0;
border-top: 6px solid #333;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
}
}
</style>
为什么没有采取 scrollWidth
通过 DOM 节点对象的 scrollWidth 属性获取到的 width 就是当前节点的内容的真实宽度,但是,源码中依然使用了 range 做了替代,为什么要这么做呢?这是因为在火狐浏览器的旧版本中存在一个 bug。
scrollWidth 属性在火狐浏览器 v32 版本中有 bug。当元素的 CSS 属性中使用了 text-overflow: ellipsis 和 box-sizing: border-box 时获取到的 scrollWidth 的值会比真实值偏小。
bug地址:bugzilla.mozilla.org/show_bug.cg…
参考链接:
Element.scrollWidth: developer.mozilla.org/zh-CN/docs/…
Document.createRange: developer.mozilla.org/zh-CN/docs/…
Range API: developer.mozilla.org/zh-CN/docs/…
element plus table: github.com/element-plu…