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

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的文本展开收起组件)

呦&#xff01;大家好&#xff0c;好久没有更新博客了&#xff0c;最近实现了一个一直想自己完成的一个东西&#xff0c;就是文本的展开收起组件&#xff0c;以前项目需要用到&#xff0c;自己实现一个又太繁琐&#xff0c;所以那个时候都是用的别人的轮子&#xff0c;现在自己…...

区间预测 | MATLAB实现VAR向量自回归时间序列区间预测

区间预测 | MATLAB实现VAR向量自回归时间序列区间预测 目录 区间预测 | MATLAB实现VAR向量自回归时间序列区间预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 区间预测 | MATLAB实现VAR向量自回归时间序列区间预测 VAR(Vector Autoregression)模型是一种广泛应用于时…...

在 Windows 上搭建 NTP 服务器

文章目录 一、基础环境二、适用场景三、操作步骤四、常用的NTP服务器五、参考资料 版权声明&#xff1a;本文为博主原创文章&#xff0c;于2023年7月30日首发于CSDN&#xff0c;转载请附上原文出处链接和本声明。本文链接&#xff1a;https://blog.csdn.net/u011046671 一、基础…...

应急响应经典案例-FTP 暴力破解

应急响应经典案例-FTP 暴力破解 应急场景日志分析应急处理措施 应急场景 从昨天开始&#xff0c;网站响应速度变得缓慢&#xff0c;网站服务器登录上去非常卡&#xff0c;重启服务器就能保证一段时间的正常访问&#xff0c;网站响应状态时而飞快时而缓慢&#xff0c;多数时间是…...

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启动流程源码&#xff1a; 1、启动SpringBoot启动类SpringbootdemoApplication中的main方法。 SpringBootApplication public class SpringbootdemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootdemoApplication.class, …...

【Linux】进程轻松入门

目录 一&#xff0c; 冯* 诺依曼体系结构 1&#xff0c;存储结构 ​编辑 二&#xff0c; 操作系统 1&#xff0c;概念 2&#xff0c;设计OS的目的 3&#xff0c;定位 4&#xff0c;如何理解 "管理" 5&#xff0c; 总结 三&#xff0c;进程 1. 概念 那么…...

【使用时空RBF-NN进行非线性系统识别】实现了 RBF、分数 RBF 和时空 RBF 神经网络,用于非线性系统识别研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Tomcat 安装配置教程及成功后,启动失败报错解决方案

解决方案 我的报错原因是因为我的JDK是1.8的而我的Tomcat是10版本的&#xff0c;可能是因为版本原因吧&#xff0c;我重新装了Tomcat 9就可以启动成功了&#xff01; 简单说下安装的时候需要注意哪些步骤吧 今天我在安装tomcat10的时候&#xff0c;安装成功后&#xff0c;启…...

C#文件操作从入门到精通(2)——查看某个dll中有哪些函数

kernel32.dll中含有ini文件操作使用的函数,我们可以通过VisualStudio自带的dumpbin.exe查看dll所包含的函数,操作步骤如下: 1、找到dumpbin.exe所在的文件夹 我的电脑中安装了VisualStudio2019社区版以及VisualStudio2017Professional,但是我发现VisualStudio2019社区版中…...

二分查找算法(全网最详细代码演示)

二分查找也称 半查找&#xff08;Binary Search&#xff09;&#xff0c;它时一种效率较高的查找方法。但是&#xff0c;折半查找要求线性表必须采用顺序存储结构&#xff0c;而且表中元素按关键字 有序 排列。 注意&#xff1a;使用二分查找的前提是 该数组是有序的。 在实际开…...

draw up a plan

爱情是美好的&#xff0c;却不是唯一的。爱情只是属于个人化的感情。 推荐一篇关于爱情的美文&#xff1a; 在一个小镇上&#xff0c;有一家以制作精美巧克力而闻名的手工巧克力店&#xff0c;名叫“甜蜜之爱”。这家巧克力店是由一位名叫艾玛的年轻女性经营的&#xff0c;她对…...

抖音seo源码开发源代码开发技术分享

一、 抖音SEO源码开发&#xff0c;需要掌握以下技术&#xff1a; 抖音API接口&#xff1a;抖音提供了丰富的API接口&#xff0c;包括用户信息、视频信息、评论信息等。 数据爬取技术&#xff1a;通过抓包分析抖音接口的数据结构&#xff0c;可以使用Python等编程语言编写爬虫程…...

QEMU(Quick Emulator)

QEMU&#xff08;Quick Emulator&#xff09;是一款由法布里斯贝拉等人编写的免费的可执行硬件虚拟化的开源托管虚拟机。它可以通过动态的二进制转换模拟CPU&#xff0c;并提供一组设备模型&#xff0c;使它能够运行多种未修改的客户机OS。QEMU还可以为user-level的进程执行CPU…...

Gateway结合nacos(lb://xxx)无效问题

Gateway结合nacos无效 版本如下&#xff1a; com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.1.0 org.springframework.cloud:spring-cloud-starter-gateway:3.1.1 配置如下&#xff1a; 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( ) - 示例 以下是一个简单的示例&#xff0c;简单说明了此方法的用法- <html><head><title>The jQuery Example</title>…...

Linux vsftp三种模式的简单配置部署

环境&#xff1a;Debian 6.1.27-1kali1 (2023-05-12) vsftpd 安装 --查看是否当前系统是否已安装 apt list --installed | grep vsftpd 没有安装的话&#xff0c;就正常安装 apt-get update apt-get install vsftpd 一、匿名用户模式 分享一些不重要文件&#xff0c;任…...

6.1.tensorRT高级(1)-概述

目录 前言1. tensorRT高级概述总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-概述 课程大纲可看下面的思维…...

【Python】将M4A\AAC录音文件转换为MP3文件

文章目录 m4aaac 基础环境&#xff1a; sudo apt-get install ffmpegm4a 要将M4A文件转换为MP3文件&#xff0c;你可以使用Python中的第三方库pydub。pydub使得音频处理变得非常简单。在开始之前&#xff0c;请确保你已经安装了pydub库&#xff0c;如果没有&#xff0c;可以通…...

个性新颖纯css手风琴效果选项卡

当涉及到个性新颖的纯CSS手风琴效果选项卡时&#xff0c;有多种方法可以实现。以下是三种可能的方法&#xff1a; 三种方法实现 方法一&#xff1a;使用:target伪类和CSS过渡效果 <style>.accordion {width: 300px;}.accordion-item {overflow: hidden;max-height: 0;…...

js的sendBeacon方法介绍

js的sendBeacon方法介绍 Beacon API是一种轻量级且有效的将网页活动记录到服务器的方法。它是一个 JavaScript API&#xff0c;可帮助开发人员将少量数据&#xff08;例如分析或跟踪信息、调试或诊断数据&#xff09;从浏览器发送到服务器。 在本文中&#xff0c;我们将介绍B…...

【Tomcat---1】IDEA控制台tomcat日志输出乱码解决

一、修改IDEA的文件编码配置为UTF-8 二、修改IDEA的vmoptions文件&#xff0c;添加-Dfile.encodingUTF-8 到Tomcat目录/conf文件夹修改logging.properties 重启idea即可。采用统一的编码...

Redis学习路线(2)—— Redis的数据结构

一、Redis的数据结构 Redis是一个Key-Value的数据库&#xff0c;key一般是String类型&#xff0c;不过Value的类型却有很多&#xff1a; String&#xff1a; Hello WorldHash&#xff1a; {name: "jack", age: 21}List&#xff1a; [A -> B -> C -> C]Set…...

【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)

探究Redis服务启动的过程机制的技术原理和流程分析的指南&#xff08;持久化功能分析&#xff09; Redis提供的持久化机制Redis持久化如何工作Redis持久化的故障分析持久化频率操作分析数据库多久调用一次write&#xff0c;将数据写入内核缓冲区&#xff1f;内核多久将系统缓冲…...

IT管理者年过50后何去何从

最近面试了一位前职为IT技术及管理专家&#xff0c;知名院校硕士毕业&#xff0c;唯一不同的是&#xff0c;他是一名已过50岁的IT技术及管理者。一直知道过了50岁&#xff0c;我们估计会有很大的坎&#xff0c;但是那时候从未曾想过连我们保险公司都会因为年龄而拒绝这样优秀的…...

C++字符串题基础(进阶请看下一个文章)

打印小写字母表 #include<iostream> #include<string.h> #include<iomanip> #include<stdio.h> #include<cmath> using namespace std; int main() {char na;for(int i1;i<13;i){cout<<n;n;}cout<<endl;for(int i1;i<13;i){c…...

webpack如何实现热更新?

webpack如何实现热更新&#xff1f; 要使用 Webpack 实现热更新&#xff0c;可以按照以下步骤进行配置&#xff1a; 1.在项目中安装 Webpack 和相关的开发依赖&#xff1a; npm install webpack webpack-cli webpack-dev-server --save-dev2.创建一个名为 webpack.dev.js 的…...

REST API的基础:HTTP

在本文中&#xff0c;我们将深入探讨万维网数据通信的基础 - HTTP。 什么是超文本&#xff1f; HTTP&#xff08;超文本传输协议&#xff09;的命名源于“超文本”。 那么&#xff0c;什么是超文本&#xff1f; 想象一下由超链接组成的文本、图像和视频的混合物。这些链接充当我…...

基于Docker-compose创建LNMP环境并运行Wordpress网站平台

基于Docker-compose创建LNMP环境并运行Wordpress网站平台 1.Docker-Compose概述2.YAML文件格式及编写注意事项3.Docker-Compose配置常用字段4.Docker Compose常用命令5.使用Docker-compose创建LNMP环境&#xff0c;并运行Wordpress网站平台1. Docker Compose 环境安装下载安装查…...

thinkphp网站源码下载/百度搜图

2023年&#xff0c;低代码仍然是热点关键词&#xff0c;毫无疑问&#xff0c;我们“低代码”仍会是2023年软件行业的热门关键字。 今天探讨下传统开发跟低代码开发产品有什么区别&#xff0c;产品交付方面怎么样&#xff1f; 传统开发&#xff1a; 正常一个软件产品的开发周期都…...

苹果电脑用什么软件做网站/网络推广网上营销

分类简介: 阅读他人的代码&#xff0c;可以学到很多东西&#xff0c;从思路&#xff0c;到方案&#xff0c;一系列都可以在项目代码中体现&#xff0c;所以&#xff0c;此分类专门用于记录阅读过的项目代码&#xff0c;并在上面给出自己的理解和注释 在此&#xff0c;感谢原作者…...

在招聘网站做销售工资高吗/如何做网站推广的策略

通过startService开启的服务&#xff0c;当访问者关闭时&#xff0c;服务仍然存在&#xff1b;访问者需要与服务进行通信&#xff0c;则我们需要将访问者与服务进行绑定&#xff1b; 如果使用Context.bindService()方法启动服务&#xff0c;则在服务未创建时&#xff0c;系统会…...

wordpress 图片服务器配置/百度网站推广价格查询

登录远程SQL服务器 一 看ping 服务器IP能否ping通。 这个实际上是看和远程sql server 2000服务器的物理连接是否存在。 如果不行&#xff0c;请检查网络&#xff0c;查看配置&#xff0c;当然得确保远程sql server 2000服务器的IP拼写正确。 二 在Dos或命令行下输入telnet …...

做网站如何购买服务器/站内营销推广方案

一.小产权房签订合同注意事项 1.小产权房签订合同注意事项&#xff1a;应写明双方和小产权房的基本信息&#xff1b;价款的确定方式及总价款、付款方式、付款时间&#xff1b;交付使用条件和日期&#xff1b;质量标准承诺&#xff1b;配套基础设施和公共设施的交付承诺和责任&…...

酒店装修/河北seo网络优化师

不可逆加密 概述 单向加密&#xff0c;主要是对明文的保密和摘要提取。算法包括MD5、SHA、HMAC等。 特点 压缩性&#xff1a;任意长度的数据&#xff0c;单向加密后长度都是固定的&#xff1b;抗修改性&#xff1a;对原数据进行任何改动&#xff0c;哪怕只修改1个字节&…...