vue3 实现文本内容超过N行折叠并显示“...展开”组件

1. 实现效果

在这里插入图片描述
在这里插入图片描述

组件内文字样式取决与外侧定义
组件大小发生变化时,文本仍可以省略到指定行数
文本不超过时, 无展开,收起按钮
传入文本发生改变后, 组件展示新的文本

2. 代码

文件名TextEllipsis.vue

<template><div ref="compRef" class="wq-text-ellipsis"><div v-if="!isExpanded" class="ellipsis-content"><span>{{ truncatedText }}</span><slot v-if="textOver" name="ellipsis"><span>{{ ellipsis }}</span></slot><span v-if="textOver" class="show-more" @click="toggleExpand"><slot name="more">{{ moreText }}</slot></span></div><div v-else class="full-content"><span>{{ fullText }}</span><span class="show-less" @click="toggleExpand"><slot name="less">{{ lessText }}</slot></span></div></div>
</template><script setup lang="ts">
import { computed, reactive, ref, watch, nextTick } from 'vue';
import { useResizeObserver } from '@vueuse/core';
import { debounce } from 'lodash';type Prop = {text?: string;maxLines?: number;// 省略显示ellipsis?: string;moreText?: string;lessText?: string;
};// 定义 props
const props = withDefaults(defineProps<Prop>(), {maxLines: 3,text: '',ellipsis: '...',moreText: '展开',lessText: '收起',
});const compRef = ref<HTMLElement>();// 定义是否展开的状态
const isExpanded = ref(false);// 定义展开和收起的方法
const toggleExpand = () => {isExpanded.value = !isExpanded.value;
};// 计算截断后的文本
const truncatedText = ref(props.text);// 定义完整的文本
const fullText = computed<string>(() => props.text);
// 判断是否超过限制行数
const textOver = computed(() => truncatedText.value !== fullText.value);watch(fullText,(newValue) => {truncatedText.value = fullText.value;isExpanded.value = false;},{immediate: true,}
);// 判断是否超过限制行数
const isOver = () => {const { height, lineHeight } = getComputedStyle(compRef.value as Element);return parseFloat(height) > props.maxLines * parseFloat(lineHeight);
};// 对字符串进行二分, 直到 找到一个合适的截断位置
const refresh = async () => {// if (!isOver()) return;let left = 0;let right = props.text.length;while (left <= right) {const mid = Math.floor((left + right) / 2);truncatedText.value = props.text.slice(0, mid);await nextTick(() => {if (isOver()) {right = mid - 1;} else {left = mid + 1;}});}truncatedText.value = props.text.slice(0, left - 1);
};const init = () => {if (!isExpanded.value) refresh();
};
// 对init 进行防抖
const debounceInit = debounce(init, 50);
useResizeObserver(compRef, () => {debounceInit();
});
</script><style lang="scss" scoped>
.wq-text-ellipsis {position: relative;white-space: normal;word-break: break-all;.show-more,.show-less {//float: right;cursor: pointer;color: lightblue;margin-left: 2px;}.ellipsis-content {position: relative;}
}
</style>

这里使用到了两个外部库, 分别用于监听, 和防抖, 若没哟引入这两个库可自行封装
debounce函数封装: js之防抖函数
useResizeObserver hook封装: 这个参考第二部分的文件ResizeObserverStore.ts这里 <-可以直接跳转到指定位置

3. 使用说明

代码样例

<div class="mw6"><text-ellipsis :max-lines="3" :text="textContent"></text-ellipsis>
</div>

prop参数

name类型说明默认值
textstring内容“”
maxLinesnumber最大行数3
ellipsisstring省略时显示“…”
moreTextstring展示按钮文字“展示”
lessTextstring收起按钮文字“收起”

slot

name说明
ellipsis省略时尾部元素
more省略时按钮元素
less展开时按钮元素

4. 原理说明

主要原理利用二分法, 对字符串进行恰当的截取

// 对字符串进行二分, 直到 找到一个合适的截断位置
const refresh = async () => {let left = 0;let right = props.text.length;// left > right 时为截取合理位置while (left <= right) {const mid = Math.floor((left + right) / 2);truncatedText.value = props.text.slice(0, mid);// 下一次刷新后判断是否截取合理await nextTick(() => {// isOver()函数用来判断行数是否合理if (isOver()) {// 实际行数超过理想行数就切掉right = mid - 1;} else {// 行数符合理想行数,就得寸进尺, 向更合理出发left = mid + 1;}});}// 获取到合理位置后进行最后一次截取truncatedText.value = props.text.slice(0, left - 1);
};// 判断是否超过限制行数
const isOver = () => {const { height, lineHeight } = getComputedStyle(compRef.value as Element);return parseFloat(height) > props.maxLines * parseFloat(lineHeight);
};

本组件用到了 useResizeObserver, 主要作用是对组件元素进行监听, 当组件大小发生变化时会重新触发字符串截取操作, 并使用节流防止截取操作频繁触发

最后

如果在使用过程中出现了问题, 或者组件有没靠略到的地方, 欢迎评论或留言

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1549466.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Android性能优化相关的10个经典面试题

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 以下是一些Android性能优化面试问题&#xff0c;包括问题和参考解答&#xff1a; 1. 如何优化Android应用的启动速度&#xff1f; 答案&#…

腾讯云SDK价格总览

计费组成 SDK 授权费用&#xff1a;购买 License 或者套餐包&#xff0c;以获得音视频终端 SDK 的使用授权所需费用。 其他相关云服务费用&#xff1a;配合腾讯云其他云产品使用 SDK 时&#xff0c;产生的对应云服务费用&#xff0c;未使用相关服务不会产生费用。 计费概述 计…

鸿蒙媒体开发系列12——音频输入设备管理(AudioRoutingManager)

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 有时设备同时连接多个音频输入设备&#xff0c;需要指定音频输入设备进行音频录制&a…

LaTex符号不好记忆?

总结在Matlab中常用的LaTeX符号如下&#xff1a; 1. **希腊字母**&#xff1a; - \alpha 表示 α - \beta 表示 β - \gamma 表示 γ - \delta 表示 δ - \epsilon 表示 ε - \zeta 表示 ζ - \eta 表示 η - \theta 表示 θ - \iota 表示 ι -…

【代码】Zotero|用文章标题更新 Zotero 的参考文献引用条目信息的 Quicker 动作

如题。 目前只支持期刊和会议文章&#xff0c;并且只支持谷歌学术或 DBLP 能搜到的文章&#xff0c;知网的不支持&#xff0c;如果有人有需要我可以去试着写&#xff0c;但我很懒我看大家也没这个需求。 很早就写完了&#xff0c;一直忘记推了。 刚写完的时候心情是很激动的&a…

Python 学习笔记1 - 认识Python

一、什么是Python 1989 年圣诞节期间&#xff0c;荷兰数学和计算机科学研究学会的Guido van Rossum&#xff08;吉多.范罗苏姆&#xff09;决心开发一个新的解释程序&#xff0c;作为 ABC 语言的替代品。这门ABC语言的替代语言被取名为Python,命名来自Guido爱看的的电视剧Mont…

Secret Configmap

应用启动过程中可能需要一些敏感信息&#xff0c;比如访问数据库的用户名&#xff0c;密码或者秘钥&#xff0c;讲这些信息直接保存在容器镜像中显然不合适&#xff0c;kubernetes提供的解决方案就是Secret Secret会以密文的方式存储数据&#xff0c;避免了直接在配置文件中保…

图说数集相等定义表明“R各元x的对应x+0.0001的全体=R“是几百年重大错误

黄小宁 设集A&#xff5b;x&#xff5d;表A各元均由x代表&#xff0c;&#xff5b;x&#xff5d;中变量x的变域是A。其余类推。因各数x可是数轴上点的坐标故x∈R变为实数yx1的几何意义可是&#xff1a;一维空间“管道”g内R轴上的质点x∈R(x是点的坐标)沿“管道”g平移变为点y…

Java爬虫:获取SKU详细信息的艺术

在电子商务的世界里&#xff0c;SKU&#xff08;Stock Keeping Unit&#xff0c;库存单位&#xff09;是每个商品的唯一标识符&#xff0c;它包含了商品的详细信息&#xff0c;如尺寸、颜色、价格等。对于商家和开发者来说&#xff0c;获取商品的SKU详细信息对于库存管理、订单…

二阶低通滤波器(Simulink仿真)

1、如何将S域传递函数转为Z域传递函数 传递函数如何转化为差分方程_非差分方程转成差分方程-CSDN博客文章浏览阅读4.1k次,点赞4次,收藏50次。本文介绍了如何将传递函数转化为差分方程,主要适用于PLC和嵌入式系统。通过MATLAB的系统辨识工具箱获取传递函数,并探讨了离散化方…

pcs集群表决盘故障导致主机reboot

建议重建fence设备并配置 PCSOracle HA实战安装配置参考 - 墨天轮

如何通过GSR排名系统迅速提升谷歌排名?

如果你希望在谷歌上迅速提升某个关键词排名&#xff0c;或者某个关键词无论怎么优化都无法上首页&#xff0c;那么GSR关键词排名系统你就可以关注一下&#xff0c;GSR系统可以在短时间内帮助你进一步提升至首页。与传统的SEO方法不同&#xff0c;GSR侧重于外部优化&#xff0c;…

使用世界领先的 Qwen2.5-Math 开源模型当 AI 数学老师,让奥数解题辅导不在鸡飞狗跳(文末有福利)

在上篇文章中&#xff0c;我们使用Qwen2.5-Coder编写了一个自动编程的多智能体系统&#xff08;基于 Qwen2.5-Coder 模型和 CrewAI 多智能体框架&#xff0c;实现智能编程系统的实战教程&#xff09;&#xff0c;着实感受到了Qwen2.5-Coder和CrewAI强强联合所发挥出来的强大威力…

学习鸿蒙Harmong基础(二)

1.类声明和使用 class Perpon { name : string "小赵"; age : number 24; isShow :boolean true; // 构造函数 constructor(name:string,age:number,isShow:boolean){ this.name name; this.age age; this.isShow isShow } puperyInfo(){ if (this.isShow) { …

芝士AI写作有什么特色? 大模型支撑,智能改写续写,让写作更轻松

又到了一年的毕业季&#xff0c;大学四年眨眼间匆匆就过去了&#xff0c;毕业&#xff0c;求职&#xff0c;考研&#xff0c;工作&#xff0c;升学&#xff0c;但是在这之前&#xff0c;我们必须要完成论文的写作&#xff0c;这也是每一位大学生都必须要面对~ 芝士AI官网&…

Java Statement SqlTemplate 源码分析

Java Statement SqlTemplate 源码分析 目录概述需求&#xff1a; 设计思路实现思路分析1. 概述2. 关键类3. 主要功能4. 源码结构5. 示例代码6. 性能考虑7. 常见问题8. 总结&#xff1a; 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show y…

在传销案件中数据库取证的分步指南

金字塔计划的特点是分层结构&#xff0c;主要由招募新成员的机制驱动。取证部门调查这些方案时&#xff0c;往往依靠数据库记录来分析这种结构。这些记录详细描述了上级和下级之间的关系&#xff0c;使调查人员能够描绘出组织的动态。在本文中&#xff0c;我们将探讨如何利用数…

解锁初中学习新境界 —— 初中通关宝典速记手册

在初中这个学习生涯的关键阶段&#xff0c;掌握扎实的基础知识是取得优异成绩的关键。为此&#xff0c;我们特别推荐《初中通关宝典》——一本专为初中生打造的各科基础知识速记手册&#xff0c;它将成为你学习路上的得力助手。 文章目录 1. 全科覆盖&#xff0c;精准速记2.科学…

Spring--boot自动配置原理案例--阿里云--starter

Spring–boot自动配置原理案例–阿里云–starter 定义这个starter的作用是它可以将阿里云的工具类自动放入IOC容器中&#xff0c;供人使用。 我们看一看构建starter的过程&#xff0c;其实就是在atuoconfigure模块中加入工具类&#xff0c;然后写一个配置类在其中将工具类放入…

Hadoop三大组件之YARN(一)

YARN架构与任务提交流程详解 1. YARN的组成架构 YARN&#xff08;Yet Another Resource Negotiator&#xff09;是Hadoop生态系统中的一个重要组成部分&#xff0c;主要用于资源管理和调度。YARN的架构主要由以下几个关键组件构成&#xff1a; 1.1 ResourceManager&#xff…