接到需求需要只在一行内显示多个标签,且标签超出输入框时超出的标签不显示,只显示统计数字的标签。
效果图:
网上查资料,发现一篇大佬的文章跟该需求很类似,就借用了大佬的写法,文章链接看这里。
后面发现还是有两个地方需要做下微调整。
1、需要数字标签紧跟着文字标签的后面排列,不能一直固定在右边
2、当页面同时有多个el-select组件时目前的写法会监听不到我们想监听的el-select组件,所以必须要保证被监听的组件的唯一性
调整后的代码如下:
html
<el-select v-model="values" multiple style="width:100%" placeholder="请选择" @change="handleChange" > <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" > </el-option> </el-select>
props
props: { options: { type: Array, default: () => [] }, value: { type: Array, default: () => [] } }
mounted
mounted() { let tagLIstDom = document.querySelector(".el-select__tags"); // 需要加上组件自定义的类名,防止监听失效 let tagSpanDom = document.querySelector(".select-tags .el-select__tags > span"); let hideDom = document.createElement("span"); hideDom.classList = ["count-node"]; //设置样式 tagSpanDom.append(hideDom); //插入到span中 var config = { childList: true }; // 当观察到突变时执行的回调函数 var callback = function(mutationsList) { mutationsList.forEach(function(item, index) { if (item.type == "childList") { let tagList = item.target.childNodes; let tagWidth = 0; //标签总宽度 let tagNum = 0; //标签多余个数 let avaliableTagWidth = 0 //显示标签的总宽度 for (let i = 0; i < tagList.length; i++) { const e = tagList[i]; if (tagWidth > tagLIstDom.offsetWidth) { e.style.display = "none"; //隐藏多余标签 } else { e.style.display = "inline-block"; //显示标签 } tagWidth += e.offsetWidth + 5; if (tagWidth > tagLIstDom.offsetWidth) { e.style.display = "none"; //隐藏多余标签 } else { e.style.display = "inline-block"; //显示标签 } if (e.style.display != "none") { tagNum++; hideDom.style.display = "none"; //隐藏多余标签个数 const margin = tagNum === 1 ? 0 : 7 avaliableTagWidth += e.offsetWidth + margin } else { hideDom.style.display = "inline-block"; //显示多余标签个数 hideDom.style.left = `${avaliableTagWidth}px` //数字标签的位置设置 hideDom.innerHTML = `+${tagList.length - tagNum}`; //显示多余标签个数 } } } }); }; // 创建一个链接到回调函数的观察者实例 observer = new MutationObserver(callback); // 开始观察已配置突变的目标节点 observer.observe(tagSpanDom, config); // 随后,您还可以停止观察 // observer.disconnect(); },
其他
methods: { handleChange() { this.$emit("change", this.value); } }, computed: { values: { get() { return this.value; }, set(val) { this.$emit("input", val); } } }, //销毁时 beforeDestroy() { // 停止观察 observer.disconnect(); }
style
<style> .count-node { position: absolute; top: 2px; display: none; height: 24px; padding: 0 8px; line-height: 22px; margin-left: 6px; background-color: #f4f4f5; border: 1px solid #e9e9eb; border-radius: 4px; color: #909399; font-size: 12px; box-sizing: border-box; } </style>
父组件引用
html
设置的class类名‘select-tags’用于保证获取组件需要监听的元素的唯一性
<select-tags v-model="value1" :options="options" class="select-tags" ></select-tags>
data
options: [{ value: '选项1', label: '黄金糕' }, { value: '选项2', label: '双皮奶' }, { value: '选项3', label: '蚵仔煎' }, { value: '选项4', label: '龙须面' }, { value: '选项5', label: '北京烤鸭' }], value1: [],
标签:el,style,标签,value,let,成多选,display,select From: https://www.cnblogs.com/applesky/p/17049175.html