当前位置:   article > 正文

element ui多选下拉组件(el-select)tag数量过多处理解决办法(二次封装)_element下拉框数据过多

element下拉框数据过多

问题描述:

如下图所示,当标签选择过多时,会占用过多空间
在这里插入图片描述
期待效果:超过n行就自动省略,并可以进行展开收起,下图是实现后的效果图
在这里插入图片描述
在这里插入图片描述

实现分析:

  1. 通过extends继承el-select组件
  2. 将select源码的template部分粘贴到封装的组件中,以此来操作展开、收起等需要操作dom的部分
  3. 监听selected(已选择项)的变化来判断各种状态
  4. 定义props最大行数maxLine,使用户在使用的时候可自定义最大行数

template部分

整个template为el-select源码粘过来的,此处仅列出修改部分

以下区域若是定位,仅需要在源码select.vue文件,搜索
<transition-group @after-leave="resetInputHeight" v-if="!collapseTags">,就可以定位到修改的区域

//向第一行最外层加入了class:el-select-new
  <div class="el-select el-select-new"></div>
	.
	.
	.
      <transition-group @after-leave="resetInputHeight" v-if="!collapseTags">
        <template>
          <el-tag
            v-for="item in showTags"//标签要根据一定的条件进行展示showTags放在了computed中
            :key="getValueKey(item)"
            :closable="!selectDisabled"
            :size="collapseTagSize"
            :hit="item.hitState"
            type="info"
            @close="deleteTag($event, item)"
            disable-transitions>
            <span class="el-select__tags-text">{{ item.currentLabel }}</span>
          </el-tag>
        </template>
      </transition-group>
     //所有tag应该占的总行数大于最大行数时
      <span  v-if="lineCount > maxLine" class="text-primary expand">
        <span v-if="!expand">...</span>
        <span class="expand-button" @click.stop="expandChange">{{lineCount > maxLine && !expand? '展开' :'收起'}}</span>
      </span>  
  • 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

js部分

export default {
  extends: Select,
  props:{
    maxLine:{//超过最大行数进行省略
      type:Number,
      default:3
    }
  },
  computed:{
    showTags(){//多选框标签得展示
      return this.lineCount > this.maxLine && !this.expand ? this.selected.slice(0,this.maxLineIndex-1) : this.selected
    }
  },
  data(){
    return {
      lineCount:1,//所有tag应该占的行数
      //最大显示行(maxLine)内的最后一个元素的位置,需要通过maxLine和当前元素会占多少位置计算得来
      maxLineIndex:0,
      expand:false,//默认收起
    }
  },
  watch:{
	//监听选项得变化,经分析得出,选项内得$el为弹窗框得dom
    selected(newVal,oldVal){
      if(this.collapseTags){return}//若是标签进行api中所说的多标签汇总到一个标签进行省略,则不需要如下判断
      if(
        // 增加标签,没有出现收起的情况
        (newVal.length>oldVal.length && this.lineCount <= this.maxLine) ||
        //减少标签且出现收起的情况
        (newVal.length < oldVal.length  && this.lineCount > this.maxLine) 
      ){
        setTimeout(()=>{
/*
  整体思路是
  监听下拉框选择内容,当内容变化时,根据内容计算文本出选中时tag所要占据的空间,
  根据tag所占用空间、tag个数,容器单行总宽度等信息,
  计算出第多少个元素会超出最大行数、若是标签全选中不省略占据的总行数等信息,以下是具体实现步骤
*/
          const dom=document.querySelector('.el-select-new .el-select__tags>span')
          const allTagWidth=newVal.map(item=>this.tagWidth(dom,item.label))
          const containerWidth=document.querySelector('.el-select-new .el-select__tags').clientWidth
          let lineCount = 1//占据行数
          let nowWidth=0//当前行容纳的tag占据的宽度
          allTagWidth.forEach((width,index)=>{
            if(nowWidth + width>=containerWidth){//超出单行可容纳宽度
              lineCount += 1
              nowWidth = width//超出宽度后,把当前宽度放到下一行计算
              if(lineCount  === this.maxLine +1 ){
                this.maxLineIndex = index
              }
            }else{
              nowWidth = nowWidth + width
            }
          })
          this.lineCount = lineCount//得出所有标签占据的最大行数
        },100)
      }
    },
    //监听展示的标签,每当展示标签变化时,调用组件内容已有的方法重新计算input的高度来重绘
    showTags(){
      this.resetInputHeight()
    },
  },
  methods:{
  //点击展开收起
    expandChange(){
      this.expand=!this.expand
    },
    //根据dom获取每个tag所占用的宽度,包括margin
    getTagSpace(dom){
      const marginLeft=Number(getComputedStyle(dom).marginLeft.replace('px',''))
      const marginRight=Number(getComputedStyle(dom).marginRight.replace('px',''))
      const offsetWidth=dom.offsetWidth
      return marginLeft + marginRight + offsetWidth
    },
    //fatherDom为父容器,text为内容,此方法是计算text所生成的tag在fatherDom中所占据宽度
    tagWidth(fatherDom,text){
      const spanOut = document.createElement('span')
      const spanInner =document.createElement('span')
      const i =document.createElement('i')
      spanOut.setAttribute('class','el-tag el-tag--info el-tag--mini el-tag--light')
      spanInner.setAttribute('class','el-select__tags-text')
      i.setAttribute('class','el-tag__close el-icon-close zzzz')
      spanInner.innerText=text
      spanOut.appendChild(spanInner)
      spanOut.appendChild(i)
      fatherDom.appendChild(spanOut)
      const width = this.getTagSpace(spanOut)
      fatherDom.removeChild(spanOut)
      return width
    }
  },
}
  • 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
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

组件的使用:

collapse-tags:false && multiple :true
传入maxLine就可以自定义省略行数,默认三行

喜欢的话记得点赞、关注、收藏多多支持,有问题的话可以评论或私聊,会及时进行反馈!

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/114816
推荐阅读
相关标签
  

闽ICP备14008679号