这是去年在校做项目遇到的一个需求,文章沉在草稿箱里一直没写完,主要分享一下如何实现长文本的折叠展开。
长文本超过限定行数自动折叠,点击长文本或者按钮,实现展开收起效果。这类效果其实在平时的app中或者网站中很常见,举几个栗子:
微信朋友圈:
新浪微博:
分析需求
1、文本超长省略,主要是通过 line-clamp 实现:
.text-clamp2 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
文本效果:
2、如何判断文本是否超出两行,显示「全文」「收起」按钮呢?
通过上图我们可以发现,当文本区域省略时,它的高度会相对变小,那么我们只需要获取到不省略和省略时的文本区域高度,进行比较就能知道是否超出了两行。
思路解决了,怀着喜悦的心情翻看了一下文档:咦?为什么小程序没有像 js 那样操作 dom 节点的接口?那还怎么获取元素的尺寸高度!好在功夫不负有心人,终于在文档找到类 DOM 操作的 API「SelectQuery」。
实现需求
3、什么是 SelectQuery?如何去使用它?
从文档(传送门)描述来看 SelectQuery 是一个查询节点信息的对象,它可以选择匹配选择器的所有节点以及显示区域内的节点信息。既然它可以类似 jQuery 那样去匹配选择器,那么我们可以获取到需要的高度信息了。
// wxml
<view class="contentInner1 text-clamp2">小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。</view>
<view class="contentInner2">小程序是一种新的开放能力,开发者可以快速地开发一个小程序。小程序可以在微信内被便捷地获取和传播,同时具有出色的使用体验。</view>
// js
wx.createSelectorQuery().selectAll(".contentInner1, .contentInner2").boundingClientRect(res => {
console.log(res)
}).exec()
查询结果(文本区域省略时高度为 52px、不省略时为 104px,只要 res[0].height < res[1].height,此时就应该显示展开收起按钮 )
4、逻辑设计上的优化
由于论坛帖子不只一个,我们得匹配对应的两个长文本节点,如果都给一个唯一的选择器,那么在页面中一次性查询这么多节点,很明显这不是最优的。
实际上我们可以将这封装成一个自定义组件,可供每个页面循环复用,在组件内我们只需要关注 单个 长文本的节点信息,不需要一次性获取当前页面的所有长文本节点,更重要的是:在组件内每个长文本的展开与收起状态都是独立的,也省去了在页面内定义字段去标识每个帖子的展开状态。
5、实现效果
6、参数说明
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
content | String | “示例文本” | 长文本内容 |
maxline | Number | 1 | 最多展示行数[只允许 1-5 的正整数] |
position | String | “left” | 展开收起按钮位置[可选值为 left right] |
foldable | Boolean | true | 点击长文本是否展开收起 |
很完美了
啊啊啊啊,我真的要哭了,text-clamp属性不生效怎么办
display: -webkit-box;
-webkit-line-clamp: 5; /* 显示的行数 */
-webkit-box-orient: vertical; /* 内容会垂直堆叠 */
overflow: hidden; /* 隐藏溢出的内容 */
text-overflow: ellipsis; /* 当内容被裁剪时显示省略号 */
}
好用!!!
太牛了,好人一生平安
大佬,有两个问题,可否指导处理一下?
1.展开时,行间距会变大,视觉很明显。把css里的字号去掉,就好了,但是字又太大了…
2.长文本 把view改为text后,加上user-select="true",自动收起就失效了。是冲突了吗?
想请教一下,想你上面举例的微博样式而言,省略号位于一行的中间位置,而不是一行末尾,这种情况要怎么实现呢,能否提供一个解决思路,谢谢。
牛哇牛哇
真不戳啊