TextClamp for Vue3.0(Vue3.0的文本展开收起组件)
呦!大家好,好久没有更新博客了,最近实现了一个一直想自己完成的一个东西,就是文本的展开收起组件,以前项目需要用到,自己实现一个又太繁琐,所以那个时候都是用的别人的轮子,现在自己尝试了一下,居然实现了,所以在这里向各位分享一下。(郑重声明,实现肯定有很多种方法,下面的只是我自己原创的方法,不喜勿喷)代码其实很简单,注释也很详细,具体的实现效果也还是不错的,现在在下面贴一下代码:
npm包的链接在这里:text-clamp-for-vue3 - npm (npmjs.com)
TextClamp.vue
<script setup lang="ts">
import { addListener, removeListener } from 'resize-detector'
import { ref, onMounted, onUnmounted } from 'vue'
import $ from 'jquery'
const props = withDefaults(defineProps<{text: string; // 传入的文本,必传项buttonType?: 'oneLine' | 'tight'; // 展开收起按钮分为:1. oneLine:自身占据单行 2. tight:和文字紧密相邻maxLines?: number; // 设置的显示的行数isExpanded?: boolean; // 展开的状态,true:展开,false:收起
}>(), {buttonType: 'oneLine',isExpanded: false,maxLines: 3
})
const textClampRef = ref<HTMLElement | null>(null) // 最外层div的ref
// const textClampContainerRef = ref<HTMLElement | null>(null) // 该组件放内容的容器的ref
const textRef = ref<HTMLElement | null>(null) // 该组件放文本内容的ref
const toggleButtonRef = ref<HTMLElement | null>(null)
const expanded = ref(props.isExpanded) //本地的expanded状态,先获取一遍属性中的isExpanded状态,然后才能用toggle方法进行修改
const step = ref<number>(200) // 截取文本的位置
// 这个是按钮为单行的模式下的折叠文本的css
const clampClass = ref({'display': '-webkit-box','-webkit-box-orient': 'vertical','-webkit-line-clamp': `${props.maxLines}`,// 这里可以根据给定的行数设置具体的clamp行数,这也是我要将css封装成一个对象的目的'overflow': 'hidden','text-overflow': 'ellipsis'
})
// 往右移动一个步长,注意我在这里将步长设置为了2,因为如果设置为1的时候,出现按钮不能紧密收紧的情况比较频繁,设置为2之后基本就正常了
function moveRight() {step.value = step.value + 2
}
// 往左移动一个步长
function moveLeft() {step.value = step.value - 2
}
/*** 获取一下展开收起按钮的宽度*/
function getButtonWidth() {// 按钮const buttonElement = $('#textRefSpan').next()[0]// 文本容器const textContainer = textClampRef.value// 按钮的宽const buttonWidth = buttonElement.clientWidth// 按钮容器的宽const textContainerWidth = textContainer?.clientWidth// return出去给其他方法用return { buttonWidth, textContainerWidth }
}
/*** ?将文本进行折叠(只在按钮的类型为tight的时候发挥作用)* *具体实现思路:先随便假定一个截取范围,例如我这里给的是[0,200],然后截取完对比下rect的宽度和maxLines,若maxLines < rect.length,则左移;若maxLines > rect.length,则右移;若相等,则调用tightText()收紧文本*/
function clampText(tag?: string) {// 要在expand为false即收起的状态时或者tag为'canClamp'时即’可以折叠‘时才执行这个函数的函数体,这样做的原因是文本有可能在展开的状态下用户调整了浏览器的宽度,这样的话,展开收起按钮可能会因为expand的变化而不断变化,这样体验就差了if (!expanded.value || tag == 'canClamp') {// 先让textRef的内容从0截取到step,step是我随便设置的,设置为200,你也可以设置为其他值,我的想法是先设置为200,然后再调整,然后再逐步收紧textRef.value && (textRef.value.textContent = props.text.slice(0, step.value) + '...')const rects = textRef.value?.getClientRects()if (rects) {console.log('rects:', rects);if (props.maxLines < rects?.length) {moveLeft();} else if (props.maxLines > rects?.length) {moveRight();} else {tightText()return}// 也需要递归调用一下自己,使文本的实际行数和给定的maxLines保持一致clampText();}}
}
/*** 收紧文本,使按钮紧贴文本的省略号*/
function tightText() {// 获取一下按钮和textContainer的宽度const { buttonWidth, textContainerWidth } = getButtonWidth()// 获取一下文本有几行(即有几个矩形)const rects = textRef.value?.getClientRects()// 如果rects或者textContainerWidth都存在的话sif (rects && textContainerWidth) {// 判断一下最后一个矩形的宽度加上按钮的宽度是否小于等于容器的宽度,如果是的话,就直接return,这个时候按钮就会紧贴文本的最右边而不换行(因为这个方法递归了)if ((rects[rects.length - 1].width + buttonWidth <= textContainerWidth) && props.maxLines == rects?.length) {return}// 如果最后一个矩形的宽度加按钮的宽度会大于等于容器宽度,说明这个时候按钮如果放在文本的最末尾就会超出导致换行,所以下面要moveLeft()if (rects[rects.length - 1].width + buttonWidth >= textContainerWidth) {console.log('here:');moveLeft()// 使用moveLeft()往左边移动后,再设置一下文本textRef.value && (textRef.value.textContent = props.text.slice(0, step.value) + '...')} else {// 如果最后一个矩形的宽度加按钮的宽度会小于等于容器宽度,说明这个时候按钮如果放在文本的最末尾不会超出导致换行,但是有可能结尾空很多空间,所以下面要moveRight(),往右收紧一点moveRight()textRef.value && (textRef.value.textContent = props.text.slice(0, step.value) + '...')}// 递归调用一下自己,不断去收紧,前面有return,所以不会爆栈tightText()}
}
/*** 初始处理一下文本*/
function init() {// 当按钮是tight时,什么也不做;若按钮是oneLine时,将显示maxLines那么多行的含省略号的样式加上props.buttonType == 'tight' ? (textRef.value && (textRef.value.textContent = props.text.slice(0, step.value) + '...')) : $('#textRefSpan').css(clampClass.value)// 获取当前文本有多少行const rects = textRef.value?.getClientRects()if (rects) {// 当给定的maxLines的行数要比真正文本的行数还要小时,此时需要进行文本的截取if (props.maxLines <= rects.length) {clampText()} else {// 此时maxLines大于或者等于真正的文本行数,此时无需截取,之前将所有文本显示出来就好/*** !顺带一提,当按钮类型为oneLine时,是直接执行的这个else,因为本函数的开头在按钮为oneLine时为TextRefSpan设置了style,这会导致getClientRects只能取到一个矩形,即使用了css省略后的矩形,此时直接将textRef的内容设置为原文即可,css会自动省略,显示给定的行数*/textRef.value && (textRef.value.textContent = props.text)}}
}/*** 切换展开收起的方法*/
function toggle() {// 当按钮的类型是单行类型时if (props.buttonType == 'oneLine') {// 当前是折叠状态时,一点就变成展开状态if ($('#textRefSpan').attr('style') !== undefined) {$('#textRefSpan').removeAttr('style')} else {// 当前是展开状态,一点变成折叠状态$('#textRefSpan').css(clampClass.value)}expanded.value = !expanded.value} else {// 当按钮的类型是紧密类型时if (!expanded.value) {// 判断,若当前(即点击toggle之前)是收起的状态,那么需要将文本展开,显示未截取的原文本// 此时要将监听去掉,不然在mounted中的监听会让文本又变成省略的状态props.buttonType == 'tight' && removeListener(textClampRef.value as HTMLElement)textRef.value && (textRef.value.textContent = props.text)} else {// 若当前已经是展开了的状态了,那么需要对文本进行截取,调用截取方法clampText('canClamp')}// 切换一下展开收起的状态expanded.value = !expanded.value// 将监听加上props.buttonType == 'tight' && addListener(textClampRef.value as HTMLElement, () => {clampText()})}
}
onMounted(() => {init()// 当按钮的类型是tight时才启动这个监听器if (textClampRef.value && props.buttonType == 'tight') {addListener(textClampRef.value as HTMLElement, () => {clampText()})}
})
onUnmounted(() => {// 卸载的时候取消对textClampRef的监听if (textClampRef.value && props.buttonType == 'tight') {removeListener(textClampRef.value as HTMLElement)}
}
)
</script><template><div ref="textClampRef"><!-- <div ref="textClampContainerRef"> --><span ref="textRef" id="textRefSpan"></span><slot ref="toggleButtonRef" name="textExpandButton" :toggle="toggle" :buttonType="buttonType":isExpanded="expanded"></slot><!-- </div> --></div>
</template>
<style scoped></style>
调用方法看:App.vue
<script setup lang="ts">
import TextClamp from "./components/TextClamp.vue";
import Card from "./components/Card.vue";
import { ref, computed, onMounted } from "vue";
let str ="The ETH upgrade upgrade timeline has never been clear. The end of December last year, as well as June and August this year, are all hazy dates. This time,the core developers have provided a clear date, market confidence has increased, and the voice is loud, and Ethereum has been impacted. There aretwo voices on Ethereum 2.0 in the market, with hundreds of billions ofdollars at stake. The first is to be pessimistic, thinking that theintroduction of 2.0 with cheap gas fees and large processing capacity willallow more projects to settle in Ethereum, and that the expansion of ETH'sdemand would raise the price of ETH.The second option is to remain solidlybearish.Following 2.0, a large number of ETHs were freed, and mass sellingand homogenization rivalry became more intense.";
</script><template><Card><template #banner><img src="./assets/image3.png" /></template><template #description><TextClamp :text="str" :buttonType="'tight'" :maxLines="4"><template #textExpandButton="props"><div v-if="props.buttonType == 'oneLine'" :style="{textAlign: 'left',cursor: 'pointer',display: 'flex',justifyContent: 'flex-end'}"><button @click="props.toggle">{{ props.isExpanded ? "Collapse" : "Expand" }}</button></div><button @click="props.toggle" v-else>{{ props.isExpanded ? "Collapse" : "Expand" }}</button></template></TextClamp></template></Card>
</template><style scoped>
.logo {height: 6em;padding: 1.5em;will-change: filter;
}.logo:hover {filter: drop-shadow(0 0 2em #646cffaa);
}.logo.vue:hover {filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
大家可以自己下载下来跑一下看看:
源码的链接在这里
https://github.com/KBKUN024/TextClamp-for-Vue3.0如果大家有更好的实现,或者对代码的有什么改进的话,非常欢迎提PR,如果对你有用,麻烦你给我一个star吧哈哈。
相关文章:
TextClamp for Vue3.0(Vue3.0的文本展开收起组件)
呦!大家好,好久没有更新博客了,最近实现了一个一直想自己完成的一个东西,就是文本的展开收起组件,以前项目需要用到,自己实现一个又太繁琐,所以那个时候都是用的别人的轮子,现在自己…...
区间预测 | MATLAB实现VAR向量自回归时间序列区间预测
区间预测 | MATLAB实现VAR向量自回归时间序列区间预测 目录 区间预测 | MATLAB实现VAR向量自回归时间序列区间预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 区间预测 | MATLAB实现VAR向量自回归时间序列区间预测 VAR(Vector Autoregression)模型是一种广泛应用于时…...
在 Windows 上搭建 NTP 服务器
文章目录 一、基础环境二、适用场景三、操作步骤四、常用的NTP服务器五、参考资料 版权声明:本文为博主原创文章,于2023年7月30日首发于CSDN,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/u011046671 一、基础…...
应急响应经典案例-FTP 暴力破解
应急响应经典案例-FTP 暴力破解 应急场景日志分析应急处理措施 应急场景 从昨天开始,网站响应速度变得缓慢,网站服务器登录上去非常卡,重启服务器就能保证一段时间的正常访问,网站响应状态时而飞快时而缓慢,多数时间是…...
41. linux通过yum安装postgresql
文章目录 1.下载安装包2.关闭内置PostgreSQL模块:3.安装postgresql服务:4.初始化postgresql数据库:5.设置开机自启动:6.启动postgresql数据库7.查看postgresql进程8.通过netstat命令或者lsof 监听默认端口54329.使用find命令查找了一下postgresql.conf的配置位置10.修改postgre…...
SpringBoot启动流程及自动配置
SpringBoot启动流程源码: 1、启动SpringBoot启动类SpringbootdemoApplication中的main方法。 SpringBootApplication public class SpringbootdemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootdemoApplication.class, …...
【Linux】进程轻松入门
目录 一, 冯* 诺依曼体系结构 1,存储结构 编辑 二, 操作系统 1,概念 2,设计OS的目的 3,定位 4,如何理解 "管理" 5, 总结 三,进程 1. 概念 那么…...
【使用时空RBF-NN进行非线性系统识别】实现了 RBF、分数 RBF 和时空 RBF 神经网络,用于非线性系统识别研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
Tomcat 安装配置教程及成功后,启动失败报错解决方案
解决方案 我的报错原因是因为我的JDK是1.8的而我的Tomcat是10版本的,可能是因为版本原因吧,我重新装了Tomcat 9就可以启动成功了! 简单说下安装的时候需要注意哪些步骤吧 今天我在安装tomcat10的时候,安装成功后,启…...
C#文件操作从入门到精通(2)——查看某个dll中有哪些函数
kernel32.dll中含有ini文件操作使用的函数,我们可以通过VisualStudio自带的dumpbin.exe查看dll所包含的函数,操作步骤如下: 1、找到dumpbin.exe所在的文件夹 我的电脑中安装了VisualStudio2019社区版以及VisualStudio2017Professional,但是我发现VisualStudio2019社区版中…...
二分查找算法(全网最详细代码演示)
二分查找也称 半查找(Binary Search),它时一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字 有序 排列。 注意:使用二分查找的前提是 该数组是有序的。 在实际开…...
draw up a plan
爱情是美好的,却不是唯一的。爱情只是属于个人化的感情。 推荐一篇关于爱情的美文: 在一个小镇上,有一家以制作精美巧克力而闻名的手工巧克力店,名叫“甜蜜之爱”。这家巧克力店是由一位名叫艾玛的年轻女性经营的,她对…...
抖音seo源码开发源代码开发技术分享
一、 抖音SEO源码开发,需要掌握以下技术: 抖音API接口:抖音提供了丰富的API接口,包括用户信息、视频信息、评论信息等。 数据爬取技术:通过抓包分析抖音接口的数据结构,可以使用Python等编程语言编写爬虫程…...
QEMU(Quick Emulator)
QEMU(Quick Emulator)是一款由法布里斯贝拉等人编写的免费的可执行硬件虚拟化的开源托管虚拟机。它可以通过动态的二进制转换模拟CPU,并提供一组设备模型,使它能够运行多种未修改的客户机OS。QEMU还可以为user-level的进程执行CPU…...
Gateway结合nacos(lb://xxx)无效问题
Gateway结合nacos无效 版本如下: com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.1.0 org.springframework.cloud:spring-cloud-starter-gateway:3.1.1 配置如下: server:port: 7000 spring:application:name: springCloudGa…...
NODEJS笔记
全局对象 global/window console.log/info/warn/error/time/timeEnd process.arch/platform/version/env/kill/pid/nextTick Buffer.alloc(5,abcde) String/toString setTimeout/clearTimeout setInterval/clearInterval setImmediate/clearImmediate process.nextTi…...
无涯教程-jQuery - html( )方法函数
html(val)方法获取第一个匹配元素的html内容(innerHTML)。此属性在XML文档上不可用。 html( ) - 语法 selector.html( ) html( ) - 示例 以下是一个简单的示例,简单说明了此方法的用法- <html><head><title>The jQuery Example</title>…...
Linux vsftp三种模式的简单配置部署
环境:Debian 6.1.27-1kali1 (2023-05-12) vsftpd 安装 --查看是否当前系统是否已安装 apt list --installed | grep vsftpd 没有安装的话,就正常安装 apt-get update apt-get install vsftpd 一、匿名用户模式 分享一些不重要文件,任…...
6.1.tensorRT高级(1)-概述
目录 前言1. tensorRT高级概述总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程,之前有看过一遍,但是没有做笔记,很多东西也忘了。这次重新撸一遍,顺便记记笔记。 本次课程学习 tensorRT 高级-概述 课程大纲可看下面的思维…...
【Python】将M4A\AAC录音文件转换为MP3文件
文章目录 m4aaac 基础环境: sudo apt-get install ffmpegm4a 要将M4A文件转换为MP3文件,你可以使用Python中的第三方库pydub。pydub使得音频处理变得非常简单。在开始之前,请确保你已经安装了pydub库,如果没有,可以通…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
