Implement a content over display ellipsis and hover over to display toolTip, not over display toolTip component
Ps: This component is based on element-Plus, implemented using vue3’s latest Setup syntax sugar. If you are not clear, you can use other technology stacks according to my ideas.
background
There are many places in the project that go beyond the need to display ellipses and then hover over to display tooltips. Before this, I noticed that some of the projects that are mouse floats in all show tooltip, regardless of whether it’s over; Others go beyond the ellipsis and don’t include tooltips, which is where the user doesn’t even know the full information. I feel that this should not be the desired effect of the product. Maybe there are too many demands before, or too many people have handled this project, so we didn’t pay attention to this subtle function. Then I took advantage of the idle period of this version iteration to tidy up, looking for products one by one, in order to unify and improve this function in the project. The main technology stack for the project is VUE2, which encapsulates a component in the project. Here, I want to use vue3+ element-Plus implementation to clean up your mind and consolidate and learn the new VUe3 setup syntax sugar.
The function point
- Beyond displays ellipsis
- Show ellipsis case, mouse over to show all
- Consider customizing the content area if it is not plain text
- Consider that the content displayed in tooltip is customizable
implementation
-
Beyond the ellipsis display this actually need not say much, we directly use CSS to achieve good, is the common old three, plus the width of the limit.
<template> <div class="content" :style="{width: props.width}"> {{props.content}} </div> </template> <script setup lang="ts"> // Define the type of props interface props { content: string, width: string } // Use withDefaults to give props a default value const props = withDefaults(defineProps<props>(), { content: ' '.width: ' ' }) </script> <style> .content { overflow: hidden; white-space: nowrap; text-overflow: ellipsis } </style> Copy the code
This now allows you to override the ellipsis. Let’s call it to see what happens:
Component calling code
<script setup lang="ts"></script>
<template>
<ShowTooltip :content="content.data" width="200px"/>
</template>
Copy the code
I don’t know. It smells good after I use it. Component automatic registration, just import. Instead of writing setup Return separately, templates can be used directly. Props has a separate interface, and the previous context also separates attrs and emit… If you are interested, you can try it. So let’s get back to our component writing.
-
Show ellipsis case, mouse over to show all
-
The first step is to use the el-ToolTip component from Element-Plus.
<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"> // Define the type of props interface props { content: string, width: string } // Use withDefaults to give props a default value const props = withDefaults(defineProps<props>(), { content: ' '.width: ' ' }) </script> <style> .content { overflow: hidden; white-space: nowrap; text-overflow: ellipsis } </style> Copy the code
Now only the mouse is implemented to show the tooltip and does not distinguish whether it is exceeded or not.
-
Implement beyond to display tooltip
So let’s think about how to tell if it exceeds. It’s not hard to imagine that we can compare the width of the content with the width of the outer box. When the width of the content is greater than or equal to the width of the box, the tooltip is displayed. We can make use of the SPAN tag that is not affected by CSS styles, the width of the content is automatically stretched, so we can wrap the content around the SPAN tag, and then calculate the width, without further words, directly into the code.
<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' // Define the type of props interface props { content: string, width: string } // Use withDefaults to give props a default value const props = withDefaults(defineProps<props>(), { content: ' '.width: ' ' }) // Use isShow to control whether the tooltip is displayed let isShow = ref<boolean>(true) // Define a ref on the span tag const contentRef = ref() const isShowTooltip = function () :void { // Calculate the offsetWidth of the span tag and the offsetWidth of the box element, and assign 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> Copy the code
At this point, we’re good enough to display text content, and we’re halfway there.
-
-
Consider the case of not plain text, you can customize the content area actually to this step is relatively simple, is write slot.
<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> Copy the code
call
<ShowTooltip :content="content.data" width="200px"> <template v-slot:content>1212324323</template> </ShowTooltip> Copy the code
The main reason to consider content as a slot is because of the presence in the project: listing values in the form of tags beyond the tooltip display. I’m going to do a little bit of a reverse here.
<script setup lang="ts"></script> <template> <! -- Simple text --> <ShowTooltip :content="content.data" width="200px"/> <br/> <! Customize the content --> <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> Copy the code
-
Consider tooltip display content can be customized to take the same approach as above, will customize the area slot, and compatible with both tooltipContent and Content. Go straight to code
<template> <el-tooltip effect="dark" :content="props.tooltipContent ? props.tooltipContent : props.content" placement="top" :disabled="isShow" > <template #content> <! TooltipContent --> <slot name="tooltipContent">{{props.tooltipContent ? props.tooltipContent : props.content}}</slot> </template> <div class="content" :style="{width: props.width}" @mouseover="isShowTooltip"> <span ref="contentRef"> <! -- Give a default value with no write slot, compatible with plain text --> <slot name="content">{{props.content}}</slot> </span> </div> </el-tooltip> </template> <script setup lang="ts"> import { ref } from 'vue' // Define the type of props interface props { content: string, width: string, tooltipContent? : string }// Use withDefaults to give props a default value const props = withDefaults(defineProps<props>(), { content: ' '.width: ' '.tooltipContent: ' ' }) // Use isShow to control whether the tooltip is displayed let isShow = ref<boolean>(true) // Define a ref on the span tag const contentRef = ref() const isShowTooltip = function () :void { // Calculate the offsetWidth of the span tag and the offsetWidth of the box element, and assign 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> Copy the code
call
<ShowTooltip width="200px"> <template v-slot:tooltipContent> <span>1223214234</span> </template> <template v-slot:content> <el-tag v-for="item in tags" :key="item" class="tag-item"> {{item}}</el-tag> </template> </ShowTooltip> Copy the code
summary
This component relies on a few attributes passed in and slots thrown.
attribute
- Width: the width of the box to use beyond display… , this attribute is mandatory
- Content: indicates the text content
- TooltipContent: Displays the text content displayed in toolTip. If this attribute is not passed, the content is displayed
slot
- Content: Content slot, custom content area
- TooltipContent: ToolTip content custom area
Component complete code
<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">
<! -- Give a default value with no write slot, compatible with plain text -->
<slot name="content">{{props.content}}</slot>
</span>
</div>
</el-tooltip>
</template>
<script setup lang="ts">
import { ref, useSlots } from 'vue'
// Define the type of propsinterface props { content? : string,width: string, tooltipContent? : string }// Use withDefaults to give props a default value
const props = withDefaults(defineProps<props>(), {
content: ' '.width: ' '.tooltipContent: ' '
})
// Use isShow to control whether the tooltip is displayed
let isShow = ref<boolean>(true)
// Define a ref on the span tag
const contentRef = ref()
const isShowTooltip = function () :void {
// Calculate the offsetWidth of the span tag and the offsetWidth of the box element, and assign 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>
Copy the code
On a side note: you can do a lot more with this depending on your needs, such as click trigger, mouse over trigger tooltip, etc