JavaScript实现文本中间缩略的两种方案

 更新时间:2024年06月24日 11:04:48   作者:碎_浪  
项目中经常会遇到缩略展示文字的场景,即要求文字在一行不换行展示,超出自动展示...,常用的展示效果有两种,文字中间缩略以及文字末尾缩略,本文将通过代码示例给大家详细的讲一下这两种方案,需要的朋友可以参考下

前言

项目中经常会遇到缩略展示文字的场景,即要求文字在一行不换行展示,超出自动展示...

常用的展示效果有两种,文字中间缩略以及文字末尾缩略,效果如下所示

// 中间缩略
这是一段超长...超长文字如何展示

// 末尾缩略
这是一段超长的文字,看看超长....

对于描述之类的文本,一般选择末尾缩略,这种场景仅靠css即可快速实现。但是对于文件名之类的场景,会期望中间缩略,保留末尾的文件后缀。下面分别介绍下两种方案的实现。

末尾缩略

使用css需实现3个效果:

  • 内容超出不展示
  • 文字不会自动折行
  • 设置对应超出样式

如果在实现过程中发现样式不生效,一定是上述3个条件有不满足的。

对应css代码如下:

    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

中间缩略

中间缩略的样式,只能手动切分字符串,并在中间拼接..., 因此关键在与,如何获得要切分的起止位置。

思路整理

本例使用React实现。之所以只用js实现,一个是因为简单,第二个则是使用css的大部分方式,需要重叠两个div,用户在选中的时候,体验不太好。

  • 因为要做到通用性所以, container 的宽度是不能确定的,它的宽度需要根据它外层的父元素来决定。因此定义两层嵌套元素,外层宽度跟随父元素,并设置overflow: hidden;white-space: nowrap;。内层宽度不做限定,保证可以正常占位。
<div className="auto-ellipsis-text">
    <span className="auto-ellipsis-text-inner">{str}</span>
 </div>
.auto-ellipsis-text{
    width: 100%;
    overflow: hidden;
    white-space: nowrap;
}
  • 然后实现下宽度计算逻辑,并更新渲染节点

div.auto-ellipsis-text上增加ref,获取对应的dom句柄

const handle = useCallback(() => {
    // 获取渲染节点的句柄
    const cu = textRef.current;
    if (!cu) {
        return;
    }
    // 获取此时父元素宽度
    const width = cu.clientWidth;

    // 获取文本节点宽度
    const textChild = cu.firstElementChild as HTMLElement;
    const innerWidth = textChild.offsetWidth;
    
    // 没有超出则不处理
    if (width >= innerWidth) {
        return;
    }

    // 计算切分位置
    const splitWidth = width / 2;

    const range = document.createRange();
    const length = textChild.innerText.length;
    const arr = [];
    let countWidth = 0;
    let startIndex = 0;
    let endIndex = 0;
    // 步进为2,逐个获取对应的宽度,并在首次累计宽度大于 splitWidth 时记录起始位置,
    // 在首次剩余宽度小于 splitWidth 时,记录截止位置,停止for循环
    for (let i = 0; i < length - 2; i += 2) {
        range.setStart(textChild.childNodes[0], i);
        range.setEnd(textChild.childNodes[0], i + 2);
        const rs = range.getBoundingClientRect();
        arr.push({ index: i, width: rs.width });
        countWidth += rs.width;
        if (countWidth > splitWidth && !startIndex) {
            startIndex = i;
        }
        if (innerWidth - countWidth < splitWidth) {
            endIndex = i + 2;
            break;
        }
    }
    // 切分字符串并补充缩略符
    const newStr = text.slice(0, startIndex) + '...' + str.slice(endIndex);

    // 更新渲染节点
    setStr(newStr);
}, []);

最终实现

  • 如果每个实例都监听父元素宽度的变化,性能太差,因此补充入参version,由调用方自行监听宽度并变更version来触发更新
  • useEffect中监听versiontext的变化,先重置str,保证渲染是最新的,然后在下个事件循环中,使用上文中的方式,计算切分位置并更新文本渲染
  • 不直接依赖str是为了防止计算出问题导致的无限死循环,上条中useEffect只会在text变化或者version变化后才会执行
export default function AutoEllipsisText({
    text,
    className,
    version,
}: {
    text: string;
    className?: string;
    version?: number;
}) {
    const [str, setStr] = useState(text);
    const textRef = useRef<HTMLDivElement>(null);

    const handle = useCallback(() => {
        /* 功能函数...*/
    }, []);

    useEffect(() => {
        setStr(text);
        Promise.resolve().then(() => {
            handle();
        });
    }, [text, version]);

    return (
        <div className={`auto-ellipsis-text ${className || ''}`} ref={textRef}>
            <span className="auto-ellipsis-text-inner">{str}</span>
        </div>
    );
}

使用

  • 上述示例对应代码仓库为auto-ellipsis-text,Demo放置在这里,也可以clone仓库后直接本地运行。

调用示例

<AutoEllipsisText text="这是一个超长的文件名超长的文件名超长的文件名文件末尾在这里.txt" version={width} />

  • 对应NPM包也已经发布,有需要可以去下载

待优化项

  • 很多时候可能需要使用<em>等标签来对文本做特殊展示,需要补充对于标签元素的计算
  • 多行的文本省略,不管是居中省略还是末尾省略,可能会以补充组件的形式,实现一个最小化的组件

写在最后

以上就是JavaScript实现文本中间缩略的两种方案的详细内容,更多关于JavaScript文本中间缩略的资料请关注脚本之家其它相关文章!

相关文章

  • JavaScript如何动态创建table表格

    JavaScript如何动态创建table表格

    这篇文章主要介绍了JavaScript如何动态创建table表格,一些时候需要动态的创建和删除表格,接下来的文章中将为大家介绍下javascript是如何做到的,感兴趣的朋友不要错过
    2015-11-11
  • Electron实现自定义全量更新的详细教程

    Electron实现自定义全量更新的详细教程

    本文主要介绍如何手动实现客户端应用的自动全量更新,通过改造electron-updater实现版本,系统等字段的动态判断更新,实现后台配置不同设备,版本,系统的版本更新,可自行在后台配置定向更新,批量更新等,需要的朋友可以参考下
    2025-08-08
  • 浅谈tudou土豆网首页图片延迟加载的效果

    浅谈tudou土豆网首页图片延迟加载的效果

    经常上tudou网,发现tudou首页加载图片的功能很有意思,tudou首页从"娱乐"这个板块往下的所有视频的缩略图并不是在页面打开后就加载的,而是当用户拖动滚动条到了"娱乐"这个板块,才开始加载图片的。
    2010-06-06
  • asp知识整理笔记3(问答模式)

    asp知识整理笔记3(问答模式)

    这是关于asp知识整理的第二份笔记,只有把最基础的问题搞清楚了,才能更好的学习ASP编程。
    2015-09-09
  • 简单的js表格操作

    简单的js表格操作

    这篇文章主要为大家详细介绍了简单的js表格操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • Layui数据表格之获取表格中所有的数据方法

    Layui数据表格之获取表格中所有的数据方法

    今天小编就为大家分享一篇Layui数据表格之获取表格中所有的数据方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • jQuery 表单验证插件formValidation实现个性化错误提示

    jQuery 表单验证插件formValidation实现个性化错误提示

    这里介绍另外一个表单验证插件formValidation,这个插件与前面两个插件的最大区别在于它实现了个性化的错误提示信息,显示在表单元素右上角类似于提示条
    2009-06-06
  • javascript弹出拖动窗口

    javascript弹出拖动窗口

    在很多网页上可以看到,点击网页的某个地方能够弹出一个新窗口,并且可以在屏幕中随意拖动,通过此篇文章给大家介绍javascript弹出拖动窗口,有需要的朋友可以参考下
    2015-08-08
  • JS创建Tag标签的方法详解

    JS创建Tag标签的方法详解

    这篇文章主要介绍了JS创建Tag标签的方法,结合具体实例形式分析了javascript动态操作页面HTML元素实现tag标签功能的步骤与相关操作技巧,需要的朋友可以参考下
    2017-06-06
  • js点亮星星评分并获取参数的js代码

    js点亮星星评分并获取参数的js代码

    点亮星星评分后,点击按钮,立即获得分数参数值,方便不想使用ajax传参的朋友
    2014-07-07

最新评论