vue3.0 element-ui使用el-tooltip文本超出时,tooltip文字提示,否则不提示
实现一个内容超出显示省略号,并鼠标浮入显示tooltip,不超出的不显示tooltip组件
该篇文章系转载:DiuDiu_yang,地址:https://blog.csdn.net/qq_41261490/article/details/120415205
实现一个内容超出显示省略号,并鼠标浮入显示tooltip,不超出的不显示tooltip组件
ps:该组件是基于element-plus,使用vue3最新的setup语法糖实现的。不清楚的大家可以根据我的思路用其他技术栈实现。
背景
项目中有很多地方有超出显示省略号,然后鼠标浮入显示tooltip的需求。在这之前,我发现项目中有些是鼠标浮入都显示tooltip,无关乎是否超出;还有一些甚至超出显示省略号,而没有加tooltip,也就是这种情况用户连完整信息都不清楚。我感觉这应该不是产品想要的效果,可能是之前需求太多,或者这个项目经手的人太多,导致没有注意到这种细微的功能。然后我趁着这版本迭代的空闲期整理了一下,找产品挨个对了一下,想统一和完善项目中这种功能。项目主要的技术栈是vue2,在项目中封装了一个组件。在这里,我想着用vue3+element-plus实现,来给大家整理思路,以及巩固和学习一下vue3新setup语法糖。
功能点
1.超出显示省略号
2.显示省略号的情况下,鼠标移入显示全部
3.考虑不是纯文本的情况,即可自定义内容区
4.考虑tooltip显示的内容可自定义
实现
1.超出显示省略号
这个其实不用多说,我们直接用css来实现就好,就是常见老三样,加上宽度的限制。
-
<template> <div class="content" :style="{width: props.width}"> {{props.content}} </div> </template> <script setup lang="ts"> // 定义props的类型 interface props { content: string, width: string } // 使用withDefaults来给props赋默认值 const props = withDefaults(defineProps<props>(), { content: '', width: '' }) </script> <style> .content { overflow: hidden; white-space: nowrap; text-overflow: ellipsis } </style>
现在这样就实现了超出显示省略号。我们来调用看看效果:
组件调用代码
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
// import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';
import ShowTooltip from './showTooltip.vue';
const content = reactive({
data: '您好您好您好您好您好您好您好您好您好您好您好'
})
</script>
<template>
<ShowTooltip :content="content.data" width="200px"/>
</template>
小插曲:不用setup语法糖不知道,用了之后感觉真香。组件自动注册,只需引入就好。不用再单独写setup return,模版直接能用。props也是有单独定义的接口,之前的context也分开了attrs和emit…大家有兴趣的还是可以去尝试尝试。好言归正传,继续我们的组件编写。
显示省略号的情况下,鼠标移入显示全部
2.先实现鼠标移入显tooltip,我们这儿tooltip就使用element-plus里的el-tooltip组件。
-
<template> <el-tooltip effect="dark" :content="props.content" placement="top" > <div class="content" :style="{width: props.width}"> {{props.content}} </div> </el-tooltip> </template> <script setup lang="ts"> // 定义props的类型 interface props { content: string, width: string } // 使用withDefaults来给props赋默认值 const props = withDefaults(defineProps<props>(), { content: '', width: '' }) </script> <style> .content { overflow: hidden; white-space: nowrap; text-overflow: ellipsis } </style>
现在只是实现了鼠标移入显示tooltip,并没有区分是否超出。
3.实现超出才显示tooltip
我们先思考一下,如何判断是否超出。
其实不难想到,我们可以利用内容的width和外层盒子的宽度作对比。当内容的宽度大于等于盒子的宽度是,就显示tooltip。我们可以利用span标签不受css样式影响,宽度是内容自动撑开的,这样我们可以将内容使用span标签包裹起来,然后计算宽度,话不多说,直接上代码。
<template>
<el-tooltip
effect="dark"
:content="props.content"
placement="top"
:disabled="isShow"
>
<div class="content" :style="{width: props.width}" @mouseover="isShowTooltip">
<span ref="contentRef">{{props.content}}</span>
</div>
</el-tooltip>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 定义props的类型
interface props {
content: string,
width: string
}
// 使用withDefaults来给props赋默认值
const props = withDefaults(defineProps<props>(), {
content: '',
width: ''
})
// 使用isShow来控制tooltip是否显示
let isShow = ref<boolean>(true)
// 在span标签上定义一个ref
const contentRef = ref()
const isShowTooltip = function (): void {
// 计算span标签的offsetWidth与盒子元素的offsetWidth,给isShow赋值
if(contentRef.value.parentNode.offsetWidth > contentRef.value.offsetWidth) {
isShow.value = true
} else {
isShow.value = false
}
}
</script>
<style>
.content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis
}
</style>
-
-
到这里,已经能满足文本内容的显示了,我们也完成一半的工作了。
-
-
考虑不是纯文本的情况,即可自定义内容区
其实到这一步就比较简单了,就是写插槽。 -
<template> <el-tooltip effect="dark" :content="props.content" placement="top" :disabled="isShow" > <div class="content" :style="{width: props.width}" @mouseover="isShowTooltip"> <span ref="contentRef"> <slot name="content">{{props.content}}</slot> </span> </div> </el-tooltip> </template>
调用
<ShowTooltip :content="content.data" width="200px">
<template v-slot:content>1212324323</template>
</ShowTooltip>
考虑将内容作为插槽主要是因为项目中存在:以tag的形式列举值,超出tooltip显示。这里我大概还原一下。
<script setup lang="ts">
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup
// import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';
import ShowTooltip from './showTooltip.vue';
const content = reactive({
data: '您好您好您好您好您好您好您好您好您好您好您好'
})
const tags = reactive([
'苹果',
'梨子',
'香蕉',
'芒果',
'火龙果',
'猕猴桃'
])
</script>
<template>
<!-- 单纯的文本 -->
<ShowTooltip :content="content.data" width="200px"/>
<br/>
<!-- 将内容自定义 -->
<ShowTooltip :content="content.data" width="200px">
<template v-slot:content>
<el-tag v-for="item in tags" :key="item" class="tag-item"> {{item}}</el-tag>
</template>
</ShowTooltip>
</template>
<style>
.tag-item {
margin-left: 5px;
}
</style>
-
考虑tooltip显示的内容可自定义
采取上面同样的办法,将自定义区域slot,并且兼容两个tooltipContent 与 content。直接上代码
<template>
<el-tooltip
effect="dark"
:content="props.tooltipContent ? props.tooltipContent : props.content"
placement="top"
:disabled="isShow"
>
<template #content>
<!-- 此处的默认值先看tooltipContent有没有,没有就给默认content -->
<slot name="tooltipContent">{{props.tooltipContent ? props.tooltipContent : props.content}}</slot>
</template>
<div class="content" :style="{width: props.width}" @mouseover="isShowTooltip">
<span ref="contentRef">
<!-- 给一个没有写插槽的默认值,兼容纯文本的情况 -->
<slot name="content">{{props.content}}</slot>
</span>
</div>
</el-tooltip>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 定义props的类型
interface props {
content: string,
width: string,
tooltipContent?: string
}
// 使用withDefaults来给props赋默认值
const props = withDefaults(defineProps<props>(), {
content: '',
width: '',
tooltipContent: ''
})
// 使用isShow来控制tooltip是否显示
let isShow = ref<boolean>(true)
// 在span标签上定义一个ref
const contentRef = ref()
const isShowTooltip = function (): void {
// 计算span标签的offsetWidth与盒子元素的offsetWidth,给isShow赋值
if(contentRef.value.parentNode.offsetWidth > contentRef.value.offsetWidth) {
isShow.value = true
} else {
isShow.value = false
}
}
</script>
<style>
.content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis
}
</style>
调用
小结
这个组件我们主要依赖传入的几个属性,及抛出的slot灵活使用。
属性
width: 盒子的宽度,要使用超出显示…,该属性必填
content: 文本内容
tooltipContent: tooltip显示的文本内容,不传该属性时,显示content
slot
content: 内容插槽,自定义内容区域
tooltipContent: tooltip内容自定义区域
组件完整代码
<template>
<el-tooltip
effect="dark"
:content="props.tooltipContent ? props.tooltipContent : props.content"
placement="top"
:disabled="isShow"
>
<template #content>
<slot name="tooltipContent">{{props.tooltipContent ? props.tooltipContent : props.content}}</slot>
</template>
<div class="content" :style="{width: props.width}" @mouseover="isShowTooltip">
<span ref="contentRef">
<!-- 给一个没有写插槽的默认值,兼容纯文本的情况 -->
<slot name="content">{{props.content}}</slot>
</span>
</div>
</el-tooltip>
</template>
<script setup lang="ts">
import { ref, useSlots } from 'vue'
// 定义props的类型
interface props {
content?: string,
width: string,
tooltipContent?: string
}
// 使用withDefaults来给props赋默认值
const props = withDefaults(defineProps<props>(), {
content: '',
width: '',
tooltipContent: ''
})
// 使用isShow来控制tooltip是否显示
let isShow = ref<boolean>(true)
// 在span标签上定义一个ref
const contentRef = ref()
const isShowTooltip = function (): void {
// 计算span标签的offsetWidth与盒子元素的offsetWidth,给isShow赋值
if(contentRef.value.parentNode.offsetWidth > contentRef.value.offsetWidth) {
isShow.value = true
} else {
isShow.value = false
}
}
</script>
<style>
.content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis
}
</style>
题外话:大家可以根据需要基于此实现更多功能,比如点击触发,还是鼠标移入触发tooltip等
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)