el-select二次封装带有全选和数量统计功能

实现效果

在这里插入图片描述

组件使用

使用v-model ,v-model为已选择的列表,list为全量列表

 <select-all
    :list="moduleList"
    v-model="formData.buildModuleIds"
    width="600px"
></select-all>

二次封装el-select组件

<template>
  <div :style="{ width }" class="select-all">
    <el-select
      multiple
      v-model="selectedList"
      @change="changeSelect"
      @remove-tag="removeTag"
      placeholder="请选择"
      class="select-list"
      v-bind="$attrs"
    >
      <el-option
        v-if="list.length"
        :label="`全选(${selectCountText})`"
        value="全选"
        @click.native="selectAll"
      ></el-option>
      <el-option
        v-for="item in list"
        :key="item.value"
        :label="item.label"
        :value="item.value"
      ></el-option>
    </el-select>
    <span class="select-count" v-if="showCount && selectedList.length">
      {
    
    {
    
     selectCountText }}
    </span>
  </div>
</template>

<script>
import {
    
     cloneDeep } from 'lodash-es';
export default {
    
    
  model: {
    
    
    prop: 'selects',
    event: 'changList'
  },
  props: {
    
    
    selects: {
    
    
      type: Array,
      default: () => []
    },
    list: {
    
    
      type: Array,
      default: () => []
    },
    width: {
    
    
      type: String,
      default: '200px'
    },
    showCount: {
    
    
      type: Boolean,
      default: true
    }
  },
  data() {
    
    
    return {
    
    
      selectedList: cloneDeep(this.selects)
    };
  },
  computed: {
    
    
    selectCountText() {
    
    
      let length = this.selectedList.length;
      if (this.selectedList.includes('全选')) length = length - 1;
      return `${
      
      length}/${
      
      this.list.length}`;
    }
  },
  watch: {
    
    
    selects: {
    
    
      handler(nv) {
    
    
        if (nv.length && nv.length === this.list.length) {
    
    
          if (!this.selectedList.includes('全选'))
            this.selectedList.unshift('全选');
        }
      },
      deep: true,
      immediate: true
    },
    list: {
    
    
      handler(nv) {
    
    
        if (nv.length && nv.length === this.selects.length) {
    
    
          if (!this.selectedList.includes('全选'))
            this.selectedList.unshift('全选');
        }
      },
      immediate: true,
      deep: true
    }
  },
  methods: {
    
    
    selectAll() {
    
    
      if (this.selectedList.length < this.list.length) {
    
    
        this.selectedList = [];
        this.list.map(item => {
    
    
          this.selectedList.push(item.value);
        });
        this.selectedList.unshift('全选');
      } else {
    
    
        this.selectedList = [];
      }
      this.emitChange();
    },
    changeSelect(val) {
    
    
      if (!val.includes('全选') && val.length === this.list.length) {
    
    
        this.selectedList.unshift('全选');
      } else if (val.includes('全选') && val.length - 1 < this.list.length) {
    
    
        this.selectedList = this.selectedList.filter(item =>  item !== '全选');
      }
      this.emitChange();
    },
    removeTag(val) {
    
    
      if (val === '全选')  this.selectedList = []
      this.emitChange();
    },
    emitChange() {
    
    
      const selectedList = this.selectedList.filter(item => item !== '全选');
      this.$emit('changList', selectedList);
    }
  }
};
</script>
<style lang="scss" scoped>
.select-all {
    
    
  position: relative;
  .select-list {
    
    
    width: 100%;
  }
  .select-count {
    
    
    display: inline-block;
    line-height: 20px;
    text-align: right;
    position: absolute;
    bottom: 0;
    right: 2px;
    color: #909399;
    font-size: 12px;
  }
}
</style>

本文参考https://segmentfault.com/a/1190000019945631,并进行二次封装

猜你喜欢

转载自blog.csdn.net/weixin_44157964/article/details/120042820