赞
踩
如下图所示,当标签选择过多时,会占用过多空间
期待效果:超过n行就自动省略,并可以进行展开收起,下图是实现后的效果图
实现分析:
整个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>
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 } }, }
collapse-tags:false && multiple :true
传入maxLine就可以自定义省略行数,默认三行
喜欢的话记得点赞、关注、收藏多多支持,有问题的话可以评论或私聊,会及时进行反馈!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。