实现一个类似element table中show-overflow-tooltip的组件

170 阅读1分钟

知识点: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…

原文地址:blog.csdn.net/wangzl1163/…