省略号文本的“展开”和“收起”

151 阅读1分钟

实现效果

image.png

image.png

代码片段

<div class="app-extend-card-content">
  <div
    :class="['text', textClassName]"
    ref="textRef"
  >
    <span
      class="other"
      v-if="textClassName === 'outer' && props.text"
      @click="otherShow(true)"
    >【展开】</span>
    <span
      class="other"
      v-if="textClassName === 'inner' && oShow && props.text"
      @click="otherShow(false)"
    >【收起】</span>
    {{ props.text }}
  </div>
</div>

注意点: 按钮需要放在文本之前

.app-extend-card-content {
  width: 100%;
  padding: 20px 25px;
  box-sizing: border-box;
  background-color: #fff;
  display: flex;
  .text {
    font-size: 26px;
    font-weight: 400;
    color: #666666;
    line-height: 36px;
    margin: 0;
    &::before{
      content: '';
      float: right;
      width: 0px;
      height: calc(100% - 33px);
      background: red
    }
    &.outer {
      word-break: break-all;
      text-overflow: ellipsis;
      overflow: hidden;
      display: -webkit-box;
      -webkit-line-clamp: 2;//控制行数
      -webkit-box-orient: vertical;
      line-height: 36px;
    }
    &.inner {
      display: block;
      oveflow: auto;
    }
    .other {
      float: right;
      clear: both;
      font-size: 26px;
      font-weight: 400;
      color: rgba(31, 126, 255, 1);
      line-height: 36px;
      margin: 0;
    }
  }
}

display: -webkit-box;存在浏览器的兼容问题在safair和火狐上会出现文本不现实的问题,解决方案如下

&.outer {
  word-break: break-all;
  text-overflow: ellipsis;
  overflow: hidden;
  //display: -webkit-box;
  //-webkit-line-clamp: 2;//控制行数
  //-webkit-box-orient: vertical;
  line-height: 36px;
  max-height: 72px;
  .other::before {
    content: '...';
    font-size: 26px;
    font-weight: 400;
    color: #666666;
    line-height: 36px;
  }
}

设置内容的最大高度,做到限制行数,省略号使用给按钮添加伪元素来实现

const textRef = ref(null)

const oShow = ref(false)

const textClassName = computed(() => {
  if(oShow.value === false && (textRef.value?.offsetHeight / 20) > 2) {
    return 'outer'
  }
  return 'inner'
})

function otherShow(bol) {
  oShow.value = bol
}

完成代码

<template>
  <div class="app-extend-card">
    <div class="app-extend-card-header">
      <div class="header-box">
        <p class="title">{{ props.title }}</p>
      </div>
    </div>
    <div class="app-extend-card-content">
      <div
        :class="['text', textClassName]"
        ref="textRef"
      >
        <span
          class="other"
          v-if="textClassName === 'outer' && props.text"
          @click="otherShow(true)"
        >【展开】</span>
        <span
          class="other"
          v-if="textClassName === 'inner' && oShow && props.text"
          @click="otherShow(false)"
        >【收起】</span>
        {{ props.text }}
      </div>
    </div>
    <div class="app-extend-card-footer">
      <div class="time" />
      <div class="grade">--</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'AppExtendCard'
}
</script>

<script setup>
import {ref, computed} from 'vue'
const props = defineProps({
  title: {
    type: String,
    default: '--'
  },
  text: {
    type: String,
    default: '--'
  }
})

const textRef = ref(null)

const oShow = ref(false)

const textClassName = computed(() => {
  if(oShow.value === false && (textRef.value?.offsetHeight / 20) > 2) {
    return 'outer'
  }
  return 'inner'
})

function otherShow(bol) {
  oShow.value = bol
}

</script>

<style lang='scss'>
.app-extend-card{
  width: 100%;
  border-radius: 20px;
  overflow: hidden;
  .app-extend-card-header {
    width: 100%;
    background-color: #fff;
    .header-box {
      width: calc(100% - 50px);
      height: 80px;
      border-bottom: 1px solid #ccc;
      padding: 20px 0 0;
      margin-left: 25px;
      box-sizing: border-box;
      .title {
        font-size: 30px;
        font-weight: 400;
        color: #333333;
        line-height: 40px;
        margin: 0;
      }
    }
  }
  .app-extend-card-content {
    width: 100%;
    padding: 20px 25px;
    box-sizing: border-box;
    background-color: #fff;
    display: flex;
    .text {
      font-size: 26px;
      font-weight: 400;
      color: #666666;
      line-height: 36px;
      margin: 0;
      &::before{
        content: '';
        float: right;
        width: 0px;
        height: calc(100% - 33px);
        background: red
      }
      &.outer {
        word-break: break-all;
        text-overflow: ellipsis;
        overflow: hidden;
        //display: -webkit-box;
        //-webkit-line-clamp: 2;//控制行数
        //-webkit-box-orient: vertical;
        line-height: 36px;
        max-height: 72px;
        .other::before {
          content: '...';
          font-size: 26px;
          font-weight: 400;
          color: #666666;
          line-height: 36px;
        }
      }
      &.inner {
        display: block;
        oveflow: auto;
      }
      .other {
        float: right;
        clear: both;
        font-size: 26px;
        font-weight: 400;
        color: rgba(31, 126, 255, 1);
        line-height: 36px;
        margin: 0;
      }
    }
  }
  .app-extend-card-footer {
    width: 100%;
    height: 80px;
    background-color: #fbfbfb;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 25px;
    box-sizing: border-box;
    position: relative;
    &:before {
      content: '';
      display: inline-block;
      width: 30px;
      height: 30px;
      background-color: #e7e8ea;
      border-radius: 15px;
      position: absolute;
      left: 0;
      top: 0;
      transform: translate(-50%, -50%);
    }
    &:after{
      content: '';
      display: inline-block;
      width: 30px;
      height: 30px;
      background-color: #e7e8ea;
      border-radius: 15px;
      position: absolute;
      right: 0;
      top: 0;
      transform: translate(50%, -50%);
    }
    .grade {
      font-size: 36px;
      font-weight: 400;
      color: #0C7E00;
      line-height: 40px;
    }
  }
}
</style>