全网独家骚操作-富文本超长内容展开收起

需求

用户评论列表,每一条评论可能有很长的内容,所以产品要求如果内容>3行,则最多展示3行,下方出现按钮,可以进行’展开’、’收起’操作;

如果内容<=3行,则完整展示,并且没有任何操作按钮;

目前服务端返给前端的评论内容数据,是富文本形式;

需要达成的效果

效果展示

实现思路

点击按钮前,默认情况

需要满足以下几个条件:

  • 以行数进行计算,不要计算内容有多少个字,因为是富文本,而且可能还有乱七八糟的emoji表情,所以计算字数没有任何意义
  • 不操作DOM节点,不使用offsetHeight等高度去进行计算
  • 依靠CSS样式实现

结合以上几个条件,我们可以这样想:

  • 其实完全不用管这个评论到底要不要操作按钮,我们简单暴力地让每一条评论都有操作按钮,只不过内容超长的评论,会看见这个按钮;内容<=3行的,利用css,把这个按钮给隐藏,让它视觉上消失而已;

看一下我绘制的示意图:
示意图
因为根据UI图,我们已知每行文字的行高是42px,那么默认的展示情况就是:3行文字的高度 + 按钮的高度 = 168px,超过168px的地方,overflow隐藏,不就实现目的了吗,而且按钮绝对定位第4行的位置,按钮还有背景色,刚好就把原本第4行的文字给遮挡住了;
上面这幅图够清晰了吧,评论内容富文本正常流式布局操作按钮使用了绝对定位而已,且带了背景色起到了遮挡作用

先不要管点了操作按钮的事情,我们先实现这个默认的布局:

1
2
3
4
<div class="big-box">
<div class="content" v-html="item.content"></div>
<div class="btn-box">按钮</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.big-box{
width: 100%;
max-height: 168px; /*一定要用 max-height 去自适应高度*/
position: relative;
outline: 2px solid red;
}

/*富文本区域,只需把行高强制固定一下,颜色字体大小等根据自己的需要设置*/
.content{
width: 100%;
line-height: 42px;
}

.btn-box{
width: 100%;
height: 42px;
line-height: 42px;
font-size: 28px;
color: red;
background-color: rgba(0,0,0,0.5);
position: absolute;
top: 126px;
left: 0;
}

默认样式的效果

点击按钮后,全部显示的情况

我们这样想,全部展示的状态下,内容盒子有多高就展示多高,按钮定位在最下面的位置不就行了么;
全部展示的效果
现在我们再来想一想按钮点击后,内容全部显示的情况,先不要管任何的JS操作,只看CSS:

1
2
3
4
<div class="big-box big-box-after">
<div class="content" v-html="item.content"></div>
<div class="btn-box btn-box-after">按钮</div>
</div>

这是最终全部展示的效果,其实就是给父级盒子加了一个big-box-after样式;
按钮盒子加了一个btn-box-after样式;
就相当于,我点击按钮后,盒子上添加这个样式即可,再点击后,移除这个样式即可;

1
2
3
4
5
6
7
8
9
.big-box-after{
max-height: unset; /* 置为默认,不给数值 */
padding-bottom: 42px; /* 下方留出一行的padding,供按钮定位后占位 */
}

.btn-box-after{
top: unset; /* 置为默认,不给数值 */
bottom: 0; /* 使用bottom定位 */
}

最终完整代码

1
2
3
4
5
<!-- 如果点击了,就要完整展示,wasClick变为true,那么就有对应的 after 样式,都是vue内的动态class写法-->
<div class="big-box" :class="item.wasClick ? 'big-box-after' : '' ">
<div class="content" v-html="item.content"></div>
<div class="btn-box" :class="item.wasClick ? 'btn-box-after' : '' " @click.stop="item.wasClick = !item.wasClick">按钮</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
.big-box{
width: 100%;
max-height: 168px; /*一定要用 max-height 去自适应高度*/
position: relative;
outline: 2px solid red;
}

/*富文本区域,只需把行高强制固定一下,颜色字体大小等根据自己的需要设置*/
.content{
width: 100%;
line-height: 42px;
}

.btn-box{
width: 100%;
height: 42px;
line-height: 42px;
font-size: 28px;
color: red;
background-color: rgba(0,0,0,0.5); /*实际使用时,把按钮盒子背景色改为和页面背景色一致即可*/
position: absolute;
top: 126px;
left: 0;
}

.big-box-after{
max-height: unset; /* 置为默认,不给数值 */
padding-bottom: 42px; /* 下方留出一行的padding,供按钮定位后占位 */
}

.btn-box-after{
top: unset; /* 置为默认,不给数值 */
bottom: 0; /* 使用bottom定位 */
}

效果

总结

利用css的一系列属性,就可以制作出按钮点击前后的效果,唯一用到的js,只是做了点击状态改变而已,重点都在css

整体实现思路的精髓在于:每一条评论的按钮其实都存在,只不过行数少的地方,按钮overflow:hidden看不见而已;长评论的按钮则肉眼可见;

整体业务代码非常短小精悍,且不操作DOM,不数字数,真正做到了以行数为单位,去达成相应的效果。


全网独家骚操作-富文本超长内容展开收起
https://liujiaweb.cn/posts/49068.html
作者
Liu Jia
发布于
2022年6月24日
许可协议