el-select组件改造成多选显示多个标签加数字标签的形式

时间:2023-01-13
本文章向大家介绍el-select组件改造成多选显示多个标签加数字标签的形式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

接到需求需要只在一行内显示多个标签,且标签超出输入框时超出的标签不显示,只显示统计数字的标签。

效果图:

网上查资料,发现一篇大佬的文章跟该需求很类似,就借用了大佬的写法,文章链接看这里

后面发现还是有两个地方需要做下微调整。

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: [],

 参考资料链接 

原文地址:https://www.cnblogs.com/applesky/p/17049175.html