vue3文字数据过长显示更多的方法探讨

196 阅读5分钟

1.使用双边逼近法截取字符串长度

<template>
  <div>
    <div ref="textContainerRef" class="text-container" v-if="!isExpanded">
      <div>
        {{ displayedText }}
        <span v-if="showMoreButton">...</span>
        <span v-if="showMoreButton" @click="expandText">显示更多</span>
      </div>
    </div>
    <div v-if="isExpanded">
      {{ fullText }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, watch } from "vue";

const textContainerRef = ref(null);
const fullText =
  "这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。";
const isExpanded = ref(false);
const displayedText = ref("");
const showMoreButton = ref(false);

const expandText = () => {
  isExpanded.value = true;
};
const recursiveBinarySearch = async (text, start, end) => {
  if (start >= end) {
    displayedText.value = text.substring(0, end);
    showMoreButton.value = displayedText.value.length < fullText.length;
    return end;
  }

  const mid = Math.floor((start + end) / 2);
  displayedText.value = text.substring(0, mid) + "...查看更多";
  // console.log(displayedText.value)
  await nextTick(() => {
    if (
      textContainerRef.value.scrollHeight <= textContainerRef.value.clientHeight
    ) {
      // 继续向右搜索,寻找更长的文本
      return recursiveBinarySearch(text, mid + 2, end);
    } else {
      // 否则,向左搜索,尝试减少文本长度
      return recursiveBinarySearch(text, start, mid - 2);
    }
  });
};

onMounted(async () => {
  await recursiveBinarySearch(fullText, 0, fullText.length);
});
</script>

<style scoped>
.text-container {
  max-height: 40px;
  line-height: 20px;
  overflow: hidden;
  position: relative;
}
button {
  position: absolute;
  bottom: 0;
  right: 0;
}
</style>

效果如下

1721373122517.png

1721373142484.png

2.css浮动实现

有个问题before里的给了高度,会导致yuanqu-con最小高度就是before里的写死的高度

<template>
  <div class="yuanqu-con">
    <div class="text" ref="myDiv" v-if="iaAll === 0">
      <span class="btn" v-if="isMore === 1" @click="handleMore">查看更多</span>
      <div class="text-con" ref="textMore">
        {{ fullText }}
      </div>
    </div>
    <div v-if="iaAll === 1">
      {{ fullText }}
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, watch } from "vue";
import { is } from "./utils/is";
const fullText =
  "这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。这是一个很长的文本,它将被截断以适应两行的显示。如果文本太长,那么我们需要找到一个合适的位置来截断它。这是测试文本,看看是否真的能截断。";
const myDiv = ref(null);
const textMore = ref(null);
const isMore = ref(0);
const iaAll = ref(0);
nextTick(() => {
  // 判断div的高度是否显示按钮
  if (textMore.value.scrollHeight >= myDiv.value.clientHeight) {
    isMore.value = 1;
  } else {
    isMore.value = 0;
  }
});

function handleMore() {
  iaAll.value = 1;
}
</script>

<style scoped>
.yuanqu-con {
  width: 1139px;
  font-size: 14px;
  color: #202332;
}

.yuanqu-con .text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.yuanqu-con .text::before {
  content: "";
  float: right;
  height: 39px;
  background: #fff;
}

/* 保留注释,因为它们在 CSS 中也是合法的 */
/* .yuanqu-con .text::after {
     content: '';
     width: 100%;
     height: 65px;
     position: absolute;
     background: #fff;
 } */

.yuanqu-con .btn {
  float: right;
  clear: both;
  cursor: pointer;
  color: #4876ff;
}
</style>

 

效果如下

1721373288286.png

1721373474253.png