当前位置: 首页 > article >正文

vue渲染数组各子项实现文本超出宽度显示tooltip

vue渲染数组各子项实现文本超出宽度显示tooltip

需求背景

vue项目中,通过v-for渲染数组,子项中均存在一行描述文字。当描述文字超出固定宽度时,显示省略号并且鼠标悬浮时显示tooltip;当描述文字不超出固定宽度时则正常显示,且鼠标悬浮不显示tooltip

否决方案

否决的两个方案均基于文本宽度与容器宽度的计算,具体实现将在后续实际方案中再进行详细阐述。否决方案仅做思路阐述,不做过于具体的赘述

1.存储各子项宽度计算结果

  • 具体实现:各子项描述文字容器绑定独有的ref,页面挂载完成后遍历各ref获取到对应元素并计算文本宽度与容器宽度关系,将计算结果存储在数组中。根据该结果通过v-if进行判断是否渲染tooltip
  • 否决原因:需要计算并存储所有子项的宽度对比,在数组量较大的情况下会有一定的性能问题。且在部分情境下,还需要考虑页面resize事件后是否要重新计算的问题

2.宽度计算结果实时应用渲染

  • 具体实现:各子项描述文字容器绑定独有的ref,各子项通过v-if绑定宽度计算函数,计算函数通过ref获取到对应元素并计算文本宽度与容器宽度关系,并返回计算结果。
  • 否决原因:v-if绑定的计算函数,内部需要在页面渲染完成后才能获取到对应的元素进行计算,但是无论是使用$nextTick还是结合Promise微任务都无法做到在渲染完成后计算结果并返回用于渲染更新

实现方案

宽度计算(核心)

// clientWidth为容器宽度,scrollWidth为文本完全展示时的实际宽度
isOverflowing(element) {return element ? element.scrollWidth > element.clientWidth : false
},

tooltip控制

<!-- 固定渲染tooltip,但手动控制显隐  -->
<a-tooltip:title="item.des"placement="top":visible="visibleId == item.id">
</a-tooltip>

悬浮计算

<!-- 元素悬浮时才进行宽度计算 -->
<div:ref="'textRef_' + item.id"class="des"@mouseenter="handleMouseEnter(item.id)"@mouseleave="handleMouseLeave"
>{{ item.des }}
</div>

计算结果存储

// 处理鼠标进入事件
handleMouseEnter(id) {// 此处refs返回的是一个数组// 若并非绑定在v-for数组内部的子元素上时,refs返回的则是单个元素,需注意区分// 不一定需要refs才能获取到元素,通过事件本身传递的event对象也可获取到对应targetconst element = this.$refs['textRef_' + id][0]if (this.isOverflowing(element)) {this.visibleId = id}
},
// 处理鼠标离开事件
handleMouseLeave() {this.visibleId = ''
},

完整代码

<template><divv-for="(item, index) in list":key="index"class="module_item"><div class="module_header"><div class="module_title"><div class="title">{{ item.title }}</div><a-tooltip:title="item.des"placement="top":visible="visibleId == item.id"><div:ref="'textRef_' + item.id"class="des"@mouseenter="handleMouseEnter(item.id)"@mouseleave="handleMouseLeave">{{ item.des }}</div></a-tooltip></div></div><div class="module_content"><!-- 内容 -->  </div></div>
</template><script>
export default {data() {return {visibleId: '',list: []}},methods: {isOverflowing(element) {return element ? element.scrollWidth > element.clientWidth : false},// 处理鼠标进入事件handleMouseEnter(id) {const element = this.$refs['textRef_' + id][0]if (this.isOverflowing(element)) {this.visibleId = id}},// 处理鼠标离开事件handleMouseLeave() {this.visibleId = ''},}
}
</script><style lang="less" scoped>
.module_item {margin-top: 0.12rem;&:first-child {margin-top: 0;}.module_header {display: flex;justify-content: space-between;align-items: center;.module_title {display: flex;align-items: center;gap: 0.08rem;.title {color: #000;font-size: 0.14rem;}.des {width: 1.83rem;color: #999;font-size: 0.1rem;text-align: left;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}}}.modules {margin-top: 0.08rem;display: flex;gap: 0.08rem;}
}
</style>

总结

  1. 悬浮时计算,不需要一次性计算所有元素的计算结果,性能良好
  2. 仅存储单个宽度计算结果控制显隐,无需冗余数据
  3. 无需v-if进行判断渲染
http://www.lryc.cn/news/2392126.html

相关文章:

  • libreoffice容器word转pdf
  • AI模型升级与机器人产业落地同步推进
  • 安全编码与AI接口权限控制
  • linux centos 服务器性能排查 vmstat、top等常用指令
  • MySQL----视图的创造和使用
  • c/c++的opencv伽马噪声
  • LiveGBS国标视频平台收流模式:UDP、TCP被动与TCP主动传输模式之差异剖析
  • 跳表(Skip List)查找算法详解
  • React从基础入门到高级实战:React 核心技术 - React 与 TypeScript:构建类型安全的应用
  • Django orm详解--组成部件
  • Tomcat 使用与配置全解
  • Chrome 开发中的任务调度与线程模型实战指南
  • aws instance store 的恢复
  • 从零开始创建 Vue 3 开发环境并构建第一个 Demo
  • EasyRTC音视频实时通话助力微信小程序:打造低延迟、高可靠的VoIP端到端呼叫解决方案
  • STM32 SPI通信(软件)
  • 每日刷题c++
  • (自用)Java学习-5.19(地址管理,三级联动,预支付)
  • 【容器】docker使用问题处理
  • ChemDraw 2023|Win英文|化学结构编辑器|安装教程
  • Vue3实现提示文字组件
  • JAVA与C语言之间的差异(一)
  • 深入剖析 C 语言中的指针数组与数组指针
  • 4.1.1 Spark SQL概述
  • 【VSCode-Qt】Docker远程连接的项目UI文件在 VSCode 上无法预览
  • redis五种数据结构详解(java实现对应的案例)
  • Telnet 命令详解
  • 深度解析新能源汽车结构与工作原理
  • React 生命周期与 Hook:从原理到实战全解析
  • OpenSSL 与 C++ 搭建一个支持 TLS 1.3 的服务器