文本超过一行显示展开收起,并且拼接到文本末尾处

发布于:2023-01-06 ⋅ 阅读:(245) ⋅ 点赞:(0)

实习中遇到的说简单也简单,说容易当也不容易,想了蛮久

直接先贴实现效果,请添加图片描述
由于是改bug,页面是别人写的,这是我能完成的最终样子,
由于要完成这个搜索的带颜色提示,后端返回的只是单纯的文本,但是要给他颜色的话,就必须要整成html标签加文本的形式,这里采用了一个方法来把它替换成带有颜色的文本。直接来整篇代码

<template>
  <div class="list-item pt-23.5px pb-33px w-[calc(100vw-364px-140px)] relative">  // 最外层给了宽度
    <div
      class="text-22px cursor-pointer"
      v-html="title"
      @click="searchDetail('/product/detail')"
    ></div>
    <p class="time mt-16px mb-24px text-14px text-[#808080]">{{ item.updateTime }}</p>
    <!-- <div class="flex"> -->
    <span
      class=" content text-16px text-[#606060] "
      :class="[flag?'':'test']"
      ref ='spanha'
      v-html="content"
    ></span>
    <span @click="changeFlag"      
    v-if="showflag"                        这里采用绝对定位来设置最初情况展开的位置,根据自己情况来定位置偏移,
    :class="[flag?'':'positi']"            这里flag等于ture时,就不会有绝对定位,就会展现在文本后面
    class="text-[#015DAC] text-12px leading-21px h-21px ">{{flag?'收起':'展开'}}  
    <i class="iconfont icon-icon_sq" 
    style="font-size:6px"
    :class="[flag?'':'xz']">
    </i></span>
    <!-- </div> -->
  </div>
</template>

<script>
export default {
  name: 'ListItem',
  props: ['item', 'keyword'],
  data () {
    return {
      title: null,
      content: null,
      flag : false,
      searchValue:null,
      // 控制展开和收起是否展现
      showflag:false 
    };
  },
  watch: {
    keyword: {
      handler (newval) {
        this.searchValue = newval;
        if (this.item.name) {
          this.title = `<p>${this.setValue(this.item.name, newval)}</p>`;
        }
        if (this.item.comment) {
          this.content = `<span class="truncate test">${this.setValue(
            this.item.comment,
            newval
          )}</span>`;
        }
      },
      immediate: true,
    },
  },
  mounted () {
    // 获取这个容器的宽度来和文本宽度进行比较,如果是大于的话就得展现
    // console.log('获取到了吗',this.$refs.spanha.clientWidth);
    // console.log('文本',this.item.comment,this.item.comment.length);
    // 由于要展现...号,所以得用块级元素,所以我只能通过判断文本字符数,并且乘以字符个数来比较宽度
    // 这里的clientWidth始终是父元素的宽度,因为是块级元素,16是字体大小
    if(this.item.comment.length*16>this.$refs.spanha.clientWidth)
    {
      this.showflag = true;
    }
  },
  methods: {
    changeFlag (){
      this.flag = !this.flag;
      if(this.flag){
            this.content = `<span class="truncate2">${this.setValue(
            this.item.comment,
            this.searchValue
          )}</span>`;
      }
      else{
         this.content = `<span class="truncate">${this.setValue(
            this.item.comment,
            this.searchValue
          )}</span>`;
      } 
    },
    caseFirstValue (target, value) {
      let res = value;
      let splitArr = value.split('');
      splitArr[0] = splitArr[0].toUpperCase();
      res = splitArr.join('');
      if (target.indexOf(res) !== -1) {
        return [res, true];
      }
      return [res, false];
    },
    caseValue (target, value) {
      let res = value;
      if (target.indexOf(value.toUpperCase()) !== -1) {
        res = value.toUpperCase();
        return [res, true];
      }
      if (target.indexOf(value.toLowerCase()) !== -1) {
        res = value.toLowerCase();
        return [res, true];
      }
      return [res, false];
    },
    setValue (target, value) {
      let res = target;
      let val = value;
      if (value) {
        const caseFirstRes = this.caseFirstValue(target, value);
        const caseRes = this.caseValue(target, value);
        val = caseRes[1] ? caseRes[0] : val;
        val = caseFirstRes[1] ? caseFirstRes[0] : val;
        res = target.replace(val, `<em style="color: #f08300">${val}</em>`);
      }
      return res;
    },
    searchDetail (path) {
      this.$router.push({ path, query: { id: this.item.id, name: this.item.name } });
    },
  },
};
</script>

<style lang="less" scoped>
.list-item {
  box-shadow: 0px 1px 0px 0px #f0f0f0;
  &::marker {
    content: "";
  }
}

// 这里是把icon进行旋转,那么下箭头就变成了上箭头
.xz{
  display: inline-block;
  transform:  rotate(180deg);
}
// 由于要展现...号,所以得用块级元素,所以我只能通过判断文本字符数,并且乘以字符个数来比较宽度
.test{
    white-space: nowrap;  /*强制span不换行*/
    display:block;  /*将span当做块级元素对待*/
    overflow: hidden;  /*超出宽度部分隐藏*/
    text-overflow: ellipsis;  /*超出部分以点号代替*/
}
.positi{
   position: absolute;
   right: -50px;
   bottom: 32px;
}
</style>

讲一下核心思想,

<span
      class=" content text-16px text-[#606060] "
      :class="[flag?'':'test']"
      ref ='spanha'
      v-html="content"
    ></span>

可以看到这里就是下面展现的内容,由于是有html标签,所以是要用v-html来展示,
多次用到绑定样式的思想,以及通过flag来判断是否展现,最主要的是通过文字长度*文字大小来和容器宽度比较,如果大于容器宽度就说明多于一行,就得展现展开和收起,这里其实并不完美,完美的是要把展开也放在下划线里面的位置,不知道还会不会给我提bug,我心累!
我也看了很多方法,但是情景都不是特别符合,只好自己摸索了,菜是原罪。


网站公告

今日签到

点亮在社区的每一天
去签到