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

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

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.xdnf.cn/news/15820.html

相关文章:

  • 百炼MCP与IoT实战(三):手搓自定义MCP Server与阿里云FC配置
  • 40+个常用的Linux指令——上
  • halcon模版匹配方向的研究
  • ts学习2
  • 飞算科技:以创新科技引领数字化变革,旗下飞算 JavaAI 成开发利器
  • 人脸检测算法——SCRFD
  • 可靠消息最终一致性分布式事务解决方案
  • 基础密码协议
  • Xilinx Zynq:一款适用于软件定义无线电的现代片上系统
  • 代理模式及优化
  • 手撕Spring底层系列之:Bean的生命周期
  • C++进阶-红黑树(难度较高)
  • Docker报错:No address associated with hostname
  • 广东省省考备考(第四十九天7.18)——判断推理:位置规律(听课后强化训练)
  • 深度学习×第10卷:她用一块小滤镜,在图像中找到你
  • 基于 WinForm 与虹软实现人脸识别功能:从理论到实践
  • 洛谷 P1395 会议
  • 周志华《机器学习导论》第9章 聚类
  • Linux基本操作
  • Linux内核设计与实现 - 第3章:Linux的进程
  • 使用python读取json数据,简单的处理成元组数组
  • 2026python实战——如何利用海外代理ip爬取海外数据
  • 【机器学习】AdamW可调参数介绍及使用说明
  • Ubuntu查看Docker容器
  • 双向广搜算法详解
  • 数据结构——单调栈
  • 服务管理智能化:R²AIN SUITE 升级带来的两大功能更新哪些值得关注?
  • SQLite / LiteDB 单文件数据库为何“清空表后仍占几 GB”?——原理解析与空间回收实战
  • 告别宕机!Ubuntu自动重启定时任务设置(一键脚本/手动操作)
  • 怎么自己搭建云手机