开发过程中遇到需要根据后端返回的数据长度来判断是否需要使用el-tooltip的情况,想到el-table里面就有这种交互效果,如果不论文字是否超出容器长度都展示tooltip的话,交互效果难免会差很多,所以二次封装了这个组件:
- 给目标容器绑定mouseenter事件
- 鼠标移入后克隆一下目标元素,并取消该元素的宽度样式
- 将克隆元素插入到页面中
- 获取克隆元素的文字后将元素从页面移除
- 用文字所占宽度跟容器宽度进行对比,判断展示tooltip
注意:二次封装的组件需要接收一个双向绑定的disabled变量,该示例比较简单,大家可以根据自己的需要对组件接收的字段进行补充
代码如下:
<template>
<el-tooltip
:show-after="300"
:disabled="disabled"
:content="content"
placement="top"
>
<div class="ellipsis" @mouseenter="handleMouseSource">
{{ content }}
</div>
</el-tooltip>
</template>
<script setup>
const props = defineProps({
disabled: {
type: Boolean,
default: false,
},
content: {
type: String,
default: "",
},
});
// 注意disabled是双向绑定的,使用该组件时要用v-model:disabled = disabled
const emits = defineEmits(["update:disabled"]);
// 判断当前tooltip是否显示
const handleMouseSource = (e) => {
// 克隆原始div,但移除宽度样式(如果需要的话,也可以移除其他可能影响宽度的样式)
const cloneDiv = e.target.cloneNode(true);
// 移除克隆div的宽度样式,以确保它能根据内容扩展
cloneDiv.style.width = "fit-Content"; // 设置克隆元素的宽度为内容宽度
cloneDiv.style.visibility = "hidden"; // 隐藏克隆div,避免它影响页面布局
cloneDiv.style.position = "absolute"; // 将其定位到页面外,避免滚动条等问题
cloneDiv.style.left = "-9999px"; // 将其移动到屏幕外
// 将克隆div添加到文档中(为了测量,但不在页面上显示)
document.body.appendChild(cloneDiv);
// 获取克隆div的宽度,这就是文字所占的宽度
const textWidth = cloneDiv.offsetWidth;
// 从文档中移除克隆div
document.body.removeChild(cloneDiv);
// 对比div容器的宽度和文本的宽度,如果文本宽度>=容器宽度,则展示tooltip
emits("update:disabled", textWidth >= e.target.clientWidth);
};
</script>
<style lang="scss" scoped>
.ellipsis {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>