实现文本溢出的展开收起功能,纯 CSS 方案在网页中可行,但在小程序中存在兼容性问题。
最优的解决方案就是使用 JavaScript 的二分截断法。
看了下 vant 的 TextEllipsis 组件源码。
理解了算法的实现原理后就写了一个uniapp版本和vue3版本的展开收起组件。
算法步骤:
- 创建隐藏容器并渲染内容。
- 计算最大行高(行数 × 单行行高)。
- 使用递归算法,类似于 tail(left, content.length)。
- 取中间值,并将其写入隐藏容器。
- 等待渲染完成后获取最新高度。
- 如果隐藏容器的高度超过最大行高,则继续调用 tail,使用 left = left,right = middle。
- 否则,可能是内容太少了(或者无法再继续截断,那就返回截取的内容)。使用 left = middle,right = right 继续调用 tail。
这个算法通过不断地二分截断,寻找到最合适的截取内容。
就算是1000多字,限定2行展示,截断次数也只在10次左右。
扩展:canvas海报的文字溢出功能也可以用这个算法。
uniapp版本
下面是从源码抽离出来单独封装的uniapp和vue3版本(网页,小程序,app都测试过)
先上效果图 300多ms:
uniapp版本有一些需要注意的点,如果兼容运行在小程序和app的话。
- 在小程序中,样式计算是在渲染过程中异步进行的,必须nextTick后才能获取容器最新高度(因为小程序样式计算是异步的。所以性能比不上网页的2ms,实测是300+ms)。
- 获取元素节点信息的方法也不一样。
- 行高如果是继承的获取的就是inherit。所以需要传行高进去。
1 | js复制代码<template> |
vue3版本
先上效果图:2ms
1 | js复制代码<template> |
本文转载自: 掘金