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

组件-多行文本省略-展开收起

1、功能

需要实现下面的功能,多行文本出现省略,并且提供展开和收起按钮。

2、技术方案与实现

1、用-webkit-line-clamp 实现

-webkit-line-clamp 指定显示几行,然后display、overflow等等设置一下就好了。
省略号的位置非常正确,但是问题是兼容性一般,想在省略号后面加按钮就有点困难。

.text {overflow: hidden;display: -webkit-box;-webkit-line-clamp: 3;-webkit-box-orient: vertical;
}

2、用float手动实现

  1. 提供一个省略号的dom,然后设置为右浮动;
  2. text-container容器设置一个伪元素挤压文字和省略号,之后再让文字content上去(margin-top为负值)

问题:当一个单词不够显示距离时会完全消失,导致省略号和文本有很长的一段距离,可以用文本的截断解决,但是英文状态会把单词给截断,这样也不好。这个问题可以用绝对定位来解决,但是可能出现省略号遮住文字的问题。。。

代码如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><style>.text-container {width: 200px;height: 100px;overflow: hidden;}.text-container::before {content: '';display: block;height: 80px;}.content {margin-top: -80px;line-height: 24px;}.more {margin-right: 10px;float: right;line-height: 1;}</style><title>Document</title></head><body><div class="text-container"><div class="more">...</div><div class="content">瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁😀😍瑟尔华润国际hi哦平台警示牌日哦和家人屁</div></div></body>
</html>

效果如下:


3、react-组件

tsx:

import React, { memo, useEffect, useRef, useState } from 'react';
import CollapseText from './components/CollapseText';
import ExpendText from './components/ExpendText';
import styles from './index.scss';/*** 可展开文本组件的Props接口*/
interface Props {/** 要显示的文本内容 */text: string;/** 最大显示行数,超出后会截断显示省略号,默认为3行 */maxLines?: number;/** 自定义CSS类名 */className?: string;/** 收起按钮的文本,默认为"收起" */collapseText?: string | React.ReactNode;/** 展开按钮的文本,默认为"展开" */expandText?: string | React.ReactNode;/** 展开/收起回调 */onToggleExpansion?: (isExpanded: boolean) => void;
}/*** 可展开文本组件** 功能:* - 根据指定行数限制文本显示* - 超出行数时自动截断并显示展开按钮* - 支持展开/收起功能* - 支持自定义按钮文本** @param props - 组件属性* @returns React函数组件*/
const ExpandableText: React.FC<Props> = ({text,maxLines = 3,className = '',collapseText = <CollapseText />,expandText = <ExpendText />,onToggleExpansion,
}) => {// 控制文本是否展开的状态const [isExpanded, setIsExpanded] = useState(false);// 标记文本是否需要展开功能(即是否超出了指定行数)const [needsExpansion, setNeedsExpansion] = useState(false);// 文本容器的DOM引用,用于计算文本高度const textRef = useRef<HTMLDivElement>(null);const [peerContainerHeight, setPeerContainerHeight] = useState(0);const [containerHeight, setContainerHeight] = useState(0);/*** 检测文本是否超出指定的行数* 通过比较实际内容高度和最大允许高度来判断*/useEffect(() => {if (textRef.current) {// 获取当前元素的行高const lineHeight = parseInt(getComputedStyle(textRef.current).lineHeight);// 计算指定行数对应的最大高度const maxHeight = lineHeight * maxLines;setPeerContainerHeight(maxHeight);setContainerHeight(maxHeight);// 获取实际内容的滚动高度(包含被隐藏的部分)const actualHeight = textRef.current.scrollHeight;// 如果实际高度超过最大高度,则需要展开功能setNeedsExpansion(actualHeight > maxHeight);}}, [text, maxLines]); // 当文本内容或最大行数改变时重新检测/*** 切换文本展开/收起状态* @param e - 鼠标点击事件*/const toggleExpansion = (e: React.MouseEvent<HTMLButtonElement>) => {// 阻止事件冒泡,避免触发父级元素的点击事件e.stopPropagation();const newIsExpanded = !isExpanded;// 切换展开状态setIsExpanded(newIsExpanded);onToggleExpansion?.(newIsExpanded);// 切换展开状态时,更新容器高度if (newIsExpanded) {setContainerHeight(textRef.current?.clientHeight || containerHeight);} else {setContainerHeight(peerContainerHeight);}};return (<divclassName={`${styles['text-container']} ${className}`}style={{'--container-height': `${containerHeight}px`,'--line-height': `${24}px`,} as React.CSSProperties}>{needsExpansion && (// <span className={isExpanded ? styles.more : styles['more-position-expend']}><span className={styles['more']}>{!isExpanded && <span className={styles['more-text']}>... </span>}<span className={styles['more-button']} onClick={toggleExpansion}>{isExpanded ? collapseText : expandText}</span></span>)}<div ref={textRef} className={`${styles['content']}`}>{text}</div></div>);
};export default memo(ExpandableText);

 

css:

.text-container {height: var(--container-height);overflow: hidden;position: relative;
}
.text-container::before {content: '';display: block;height: calc(var(--container-height) - var(--line-height, 24px));
}.content {margin-top: calc((var(--container-height) - var(--line-height, 24px)) * -1);line-height: var(--line-height, 24px);
}
.more-position-expend {padding-left: 10px;position: absolute;bottom: 4px;right: 0;background: white;
}
.more {float: right;line-height: var(--line-height, 24px);
}
.more-text {font-size: 16px;
}
.more-button {margin-left: 4px;cursor: pointer;color: rgb(255, 34, 102);
}

3、END 

目前采用float的方式

http://www.lryc.cn/news/591950.html

相关文章:

  • Android性能优化之内存优化
  • 强化学习框架VeRL全面解析(架构、调试、修改与应用)
  • 云原生 DevOps 实战之Jenkins+Gitee+Harbor+Kubernetes 构建自动化部署体系
  • 【unitrix】 6.8 加一运算(add_one.rs)
  • 【问题解决】npm包下载速度慢
  • 游戏盾在非游戏行业的应用:跨界守护网络安全的新利器
  • Rust实战:高效对接Postman API
  • ArcGIS Pro+PS 实现地形渲染效果图
  • 谷歌地球与ArcGIS Pro查看三维地形
  • SpringMVC + Tomcat10
  • Git使用与管理
  • 时序数据库 Apache IoTDB 实战:基于 Kubernetes 的部署运维全指南
  • 百度权重提升技巧分析:从底层逻辑到实战策略
  • Prompt:开启与AI高效对话的钥匙
  • 客诉:危机到信任的重建
  • Python编程:从入门到实践
  • 前端基础之《Vue(23)—跨域问题》
  • 如何区别HTML和HTML5?
  • 格式转换Total Excel Converter:20 种格式XLS XLSX 批量转 PDFWord
  • 国产替代:ASP4644在电信通信设备中的测试与应用前景
  • 中国工业RFID前三品牌
  • 微型导轨在消费电子领域如何凸显高精度技术?
  • Spring介绍以及IOC和AOP的实现
  • 行为型设计模式:解释器模式
  • 2026python实战——如何利用海外代理ip爬取海外数据
  • ​​Docker 速通教程
  • 【Docker#2】容器历史发展 | 虚拟化实现方式
  • Delphi EDI 需求分析与对接指南
  • Docker 与 GPU 训练
  • 【Docker】在Linux环境下使用Dockerfile打包镜像(图文示例)