文本溢出移入Tooltip提示,我的LeText组件

前言

项目中产品有这么个要求,有些文字展示单行/2/3行,超出隐藏,鼠标移入想要知道看全文本全部信息,有时候这个文本信息还想要支持复制粘贴 类似这样的一个实现

分析

提示: 由于实现的项目主要用的element-plus库, 后面的实现可能会用到element-plus 的组件,如果是其他组件库 可以做相关替换

1.n行显示溢出控制

scss 复制代码
// 单行文本超出 用以下样式即可
.text-overflow_ellipsis {
    overflow: hidden;  /* 隐藏超出元素框的内容 */
    text-overflow: ellipsis;  /* 文本溢出时,使用省略号(...)表示溢出的文本 */
    white-space: nowrap;  /* 设置文本不换行 */
}

// 多行文本超出 可以使用以下样式
.text-overflow_ellipsis_line($line: 2) {  
    white-space: normal; // 允许内容自然换行
    text-overflow: -o-ellipsis-lastline; // 仅适用于旧版本浏览器,指定最后一行文本溢出显示省略号
    overflow: hidden; // 隐藏超出容器的内容
    text-overflow: ellipsis; // 文本溢出时显示省略号(此设置实际在多行文本中不起作用,主要是用于单行) 
    display: -webkit-box; // 作为弹性伸缩盒子模型显示。  
    -webkit-box-orient: vertical; // 设置伸缩盒子的子元素排列方式--从上到下垂直排列  
    -webkit-line-clamp: $line; // 显示的最大行数
    word-break: break-all;  // 允许单词在任何字符间断行
}

2.复制文案

ts 复制代码
/**  
* 复制文字  
* @param val  
* @param sucTxt  
* @returns {boolean}  
*/  
export function copyText(val: string, sucTxt = '复制成功~') {  
    const textarea: any = document.createElement('textarea')  
    // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域  
    textarea.readOnly = 'readonly'  
    textarea.style.position = 'absolute'  
    textarea.style.left = '-9999px'  
    textarea.value = val  
    document.body.appendChild(textarea)  
    textarea.select()  
    const res = document.execCommand('copy')  
    document.body.removeChild(textarea)
    if (res) {  
        ElMessage.success(sucTxt)  
    }
    return res  
}

3.文本超出设定的最多行数判断

  • 可以通过 触发元素的 clientHeightscrollHeight 高度比较

具体实现

html 复制代码
<template>  
<section class="le-text-wrap" ref="textTooltipRef">  
    <el-tooltip v-if="value" :visible="isShowTooltip" :placement="placement">  
        <template #content>  
            <span>{{ value }}</span>  
        </template>  
        <div class="le-text" @mouseover="handleElTooltip" @mouseleave="isShowTooltip = false"> 
            <slot>
                <el-text v-bind="textProps" class="text-overflow_ellipsis_line_2" :style="textStyle">{{ value }}</el-text>  
            </slot>  
            <!-- 复制按钮 -->  
            <el-icon class="action-icon" v-if="copy">  
                <DocumentCopy @click.stop="copyText(value)" />  
            </el-icon>  
        </div>  
    </el-tooltip>  
    <span v-else>-</span>  
</section>  
</template>
ts 复制代码
<script lang="ts" setup name="LeText">  
import { computed, ref } from 'vue'  
import type { PropType } from 'vue'  
import { copyText } from '@/utils'  
  
defineOptions({ name: 'LeText' })  
const props = defineProps({  
    value: {  
        type: String,  
        default: ''  
    },  
    copy: {  
        type: Boolean,  
        default: false  
    },  
    // tooltip 配置  
    placement: {  
    type: String,  
    default: 'top'  
    },  
    // text 配置  
    lineClamp: {  
    type: [String, Number],  
    default: 1  
    },  
    type: {  
    type: String as PropType<'primary' | 'success' | 'warning' | 'danger' | 'info'>  
    },  
    tag: {  
    type: String,  
    default: 'span'  
    }
})  
const textProps = computed(() => {  
    const { lineClamp, type, tag } = props  
    return {  
        lineClamp,  
        type,  
        tag  
    }  
})  
const textStyle = computed((): string => {  
const lineClamp = +props.lineClamp || 1  
    return `line-clamp: ${lineClamp}; -webkit-line-clamp: ${lineClamp}`  
})  
const textTooltipRef = ref()  
const visible = ref(false)  
const isShowTooltip = ref(false)  
function handleElTooltip(e: any): void {  
    const base: number = textTooltipRef.value.clientHeight  
    isShowTooltip.value = e.target.scrollHeight > base  
}  
</script>
scss 复制代码
// Text 样式  
.le-text {  
    //font-size: 14px;  
    font-size: var(--el-font-size-base);  
    display: inline-flex;  
    &-wrap {  
    }
    .action-icon {  
        margin-left: 2px;  
        padding-top: 4px;  
        //color: var(--el-color-primary);  
        color: var(--el-text-color-secondary);  
        cursor: pointer;  
        &:hover {  
        //color: var(--el-color-primary-light-5);  
        color: var(--el-color-primary);  
        }  
    }  
}
.text-overflow_ellipsis_line_2 {
    white-space: normal;
    text-overflow: -o-ellipsis-lastline;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-box-orient: vertical; 
    -webkit-line-clamp: 2;
    word-break: break-all;
}

以上就是完整的LeText组件逻辑

组件文件地址: src/components/Text.vue 项目源代码参考下面推荐

推荐

分享给大家一个Vue3 + Ts + Element-plus & Vite 搭建,开箱即用的后台管理项目, 手机端已兼容,如果觉得不错希望可以得到各位大佬的star

项目链接 github.com/LanceJiang/...
访问链接 lancejiang.github.io/Lance-Eleme...

相关推荐
returnShitBoy6 分钟前
前端面试:React hooks 调用是可以写在 if 语句里面吗?
前端·javascript·react.js
love黄甜心7 分钟前
Sass:深度解析与实战应用
前端·css·sass
goto_w1 小时前
使用elementplus的table表格遇到的问题
前端·javascript·vue.js
Moment1 小时前
如果你想找国外远程,首先让我先给你推荐这几个流行的技术栈 🤪🤪🤪
前端·后端·github
浪裡遊1 小时前
利用github部署项目
前端·github·持续部署
烂蜻蜓2 小时前
HTML 颜色名:网页色彩世界的基石
前端·css·html·html5
匹马夕阳2 小时前
Vite项目中vite.config.js中为什么只能使用process.env,无法使用import.meta.env?
开发语言·前端·javascript
只有一斤了呐2 小时前
超硬核!教你手搓一套船新架构的前端脚手架~
前端·javascript·开源
拉不动的猪2 小时前
刷刷题38(前端实现分包及组件懒加载的核心方案&&图片懒加载)
前端·javascript·面试
任磊abc2 小时前
在react当中利用IntersectionObserve实现下拉加载数据
前端·react·observer·下拉加载·intersection