需求
用户评论列表,每一条评论可能有很长的内容,所以产品要求如果内容>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; 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; }
.btn-box-after{ top: unset; bottom: 0; }
|
最终完整代码
1 2 3 4 5
| <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; 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; }
.btn-box-after{ top: unset; bottom: 0; }
|
总结
利用css
的一系列属性,就可以制作出按钮点击前后的效果,唯一用到的js
,只是做了点击状态改变而已,重点都在css
;
整体实现思路的精髓在于:每一条评论的按钮其实都存在,只不过行数少的地方,按钮overflow:hidden
看不见而已;长评论的按钮则肉眼可见;
整体业务代码非常短小精悍,且不操作DOM
,不数字数,真正做到了以行数为单位,去达成相应的效果。