el-tooltip
vue
<template>
<el-tooltip
effect="dark"
:content="props.tooltipContent ? props.tooltipContent : props.content"
placement="top"
:disabled="isShow"
popper-class="diy-tooltip"
>
<template #content>
<slot name="tooltipContent">{{ props.tooltipContent ? props.tooltipContent : props.content }}</slot>
</template>
<div>
<div
v-if="!props.multiline"
class="content"
:style="{ width: props.width ? props.width : '100%' }"
@mouseover="isShowTooltip"
>
<span ref="contentRef">
<!-- 给一个没有写插槽的默认值,兼容纯文本的情况 -->
<slot name="content">{{ props.content }}</slot>
</span>
</div>
<div v-else class="content2" :style="{ width: props.width ? props.width : '100%' }" @mouseover="isShowTooltip2">
<span ref="contentRef">
<!-- 给一个没有写插槽的默认值,兼容纯文本的情况 -->
<slot name="content">{{ props.content }}</slot>
</span>
</div>
</div>
</el-tooltip>
</template>
<script setup lang="ts">
import { ref } from "vue"
interface props {
content?: string
width?: string
tooltipContent?: string
multiline?: boolean
}
const props = withDefaults(defineProps<props>(), {
content: "",
width: null,
tooltipContent: "",
multiline: false
})
// 使用isShow来控制tooltip是否显示
let isShow = ref<boolean>(true)
// 在span标签上定义一个ref
const contentRef = ref()
const isShowTooltip = function (): void {
// 计算span标签的offsetWidth与盒子元素的offsetWidth,给isShow赋值
if (props.multiline) {
isShow.value = false
} else {
if (contentRef.value.parentNode.offsetWidth > contentRef.value.offsetWidth) {
isShow.value = true
} else {
isShow.value = false
}
}
}
const isShowTooltip2 = () => {
if (contentRef.value.offsetHeight > contentRef.value.parentNode.offsetHeight) {
isShow.value = false
} else {
isShow.value = true
}
}
</script>
<style>
.content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.content2 {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
display: -webkit-line-clamp;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.diy-tooltip {
max-width: 500px;
}
</style>
el-popover
vue
<template>
<div ref="container" class="tags-container" @mouseover="isShowPopover">
<el-popover placement="bottom-start" width="500" :disabled="isShow">
<template #reference>
<div class="tag-item" ref="tagItem">
<el-tag v-for="(tag, index) in tags" :key="index" style="margin-right: 5px">
{{ tag }}
</el-tag>
</div>
</template>
<div>
<el-tag v-for="(tag, index) in tags" :key="index" style="margin: 2px">
{{ tag }}
</el-tag>
</div>
</el-popover>
</div>
</template>
<script setup>
import { ref } from "vue"
const props = defineProps({
tags: {
type: Array,
default: () => []
}
})
const container = ref(null)
const tagItem = ref(null)
const isShow = ref(false)
const isShowPopover = () => {
const containerWidth = container.value.offsetWidth
const contentWidth = tagItem.value.offsetWidth
if (contentWidth == containerWidth) {
isShow.value = false
} else {
isShow.value = true
}
}
</script>
<style scoped>
.tags-container {
display: flex;
flex-wrap: nowrap;
overflow: hidden;
}
.tag-item {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ellipsis {
cursor: pointer;
white-space: nowrap;
}
</style>