

需求就是超过四行得有个展开按钮,点击展开显示所有内容,不超过四行的话就不需要这个按钮并显示所有内容。且按钮在段落的后面
- 首先得判断文本自否超过四行,因为这些一般都是是前端异步请求然后后端发送过来,使用了 Vue 中的 nextTick 来监听 DOM 中是数据变化。
- 接下来主要是 css 上的思路,其实可以分为两部分,如下图,标号1的部分展示前面三行,标号为2的部分会根据1的行数判断缩进的大小,然后展示第四行。最后通过背景色的控制让两者看上去是一段文字。
主要的点:
第一部分:定位在文本框左上角,是三行高度直接截断
第二部分:定位在文本框左上角,是4行高度写上省略号样式,右边空出五个字距离,然后整体缩进15个字,这样上面三行前面实际和第一部分重合,加上背景色与层级,会看的像一段文字
{padding-right: 5em;text-intent: 15em;}
第三部分:定位在右下角的展开全文的汉字,根据文本框里文本的真实高度是否大于4行来决定是否展示
<template><divclass="text-box":class="isCusp ? 'text-cusp-box' : ''"><divclass="text-desc":class="isOpen ? 'total-desc' : ''":title="title ? title+':'+content : content"><div class="text-con" ref="desc"><spanclass="text-title"v-if="title">{{title}}:</span>{{content}}</div><divclass="text-opt"v-if="isBtn"@click="change">{{isOpen ? '收起全文' : '展开全文'}}</div></div></div></template><script>export default {props: {// 文字标题title: {type: String,default: ''},// 文字内容content: {type: String,default: ''},// 是否有尖头指向isCusp: {type: Boolean,default: false}},data() {return {// 内容信息info: '',// 是否展示按钮isBtn: false,// 按钮样子isOpen: true};},methods: {change() {this.isOpen = !this.isOpen;}},mounted() {this.info = this.content;},watch: {info(val) {let descHeight = window.getComputedStyle(this.$refs.desc).height.replace('px', '');let rem = window.getComputedStyle(this.$refs.desc).lineHeight.replace('px', '');// 超过了四行if (descHeight > rem * 4) {// 显示展开收起按钮this.isBtn = true;this.isOpen = false;} else {// 不显示展开收起按钮this.isBtn = false;this.isOpen = true;}}}};</script><style lang="less" scoped>.text-box {background: #f3f6f9;padding: 16px;border-radius: 8px;.text-desc {position: relative;max-height: 144px;line-height: 36px;word-wrap: break-word;word-break: break-all;overflow: hidden;.text-con {font-size: 24px;color: #77808a;line-height: 36px;.text-title {font-weight: bold;}}// 这是展开前实际显示的内容&:after,&:before {content: attr(title);position: absolute;left: 0;top: 0;width: 100%;font-size: 24px;color: #77808a;line-height: 36px;background: #f3f6f9;}// 把最后最后一行自身的上面三行遮住&:before {display: block;overflow: hidden;z-index: 1;max-height: 108px;}&:after {display: -webkit-box;-webkit-box-orient: vertical;overflow: hidden;height: 144px;-webkit-line-clamp: 4;text-overflow: ellipsis;-webkit-box-sizing: border-box;box-sizing: border-box;text-indent: -15em;padding-right: 5em;}&.total-desc{max-height: none;}&.total-desc:before{display: none;}&.total-desc:after{display: none;}}&.text-cusp-box {position: relative;margin-top: 30px;&:before {content: '';height: 0px;width: 0px;position: absolute;top: -14px;left: 105px;margin-left: -10px;z-index: 1;border-left: 14px solid transparent;border-right: 14px solid transparent;border-bottom: 24px solid #f3f6f9;}}.text-opt {position: absolute;font-size: 24px;color: #00c0eb;line-height: 36px;bottom: 0px;right: 0;z-index: 10;}}</style>
