vue2 select下拉全选、搜索

本文详细描述了一个自定义的Vue组件FilterSelectMultiple,它是一个可过滤、多选的下拉框,用于处理组件封装、数据绑定、筛选和状态管理。文章介绍了组件的结构、props配置和关键方法的实现。
摘要由CSDN通过智能技术生成

1、组件封装

<template>
  <el-select v-model="selectValue" multiple :disabled="disabled" :filterable="false" :collapse-tags="collapseTags" v-bind="$attrs" @change="handleChange" @visible-change="handleChangeVisible" :style="{ width:$attrs.width }">
    <div class="select-input">
      <el-input v-model="filterValue" placeholder="关键词"></el-input>
    </div>
    <div class="select-dropdown">
      <li class="el-select-dropdown__item no-mark" @click="handleAll" :class="isAll ? 'selected' : ''">
        <span class="the-checkbox"></span>
        <span>全选</span>
        <span class="reverse" @click.stop="handleReverseAll">反选</span>
      </li>
    </div>
    <div class="select-dropdown">
      <el-scrollbar wrap-class="scrollbar-wrapper" style="width: calc(100% - 10px)">
        <el-option v-for="(item, index) in filterData" :key="index" :label="item[props.label]" :value="item[props.value]"  :disabled="disabledFun(item)">
          <slot :row="item">
            <span class="the-checkbox"></span>
            <span>{{ item[props.label] }}</span>
          </slot>
        </el-option>
        <el-option hidden label="" value=""></el-option>
      </el-scrollbar>
    </div>
  </el-select>
</template>

<script>
export default {
  name: 'FilterSelectMultiple',
  props: {
    value: { type: [String, Number, Array], default: (value) => null },
    selectData: { type: Array, default: () => [] },
    props: {
      type: Object,
      default: () => { return { value: 'value', label: 'label' } }
    },
    collapseTags: { type: Boolean, default: true },
    showNotSet: { type: Boolean, default: false },
    labelText: { type: String, default: '' },
    disabled: { type: Boolean, default: false },
    disabledFun: { type: Function, default: () => false }
  },
  data() {
    return {
      filterValue: '',
      selectValue: []
    }
  },
  watch: {
    value: {
      handler(val) {
        this.selectValue = val ?? []
      },
      immediate: true
    }
  },
  computed: {
    filterData() {
      return this.selectData && this.selectData.filter((item) => item[this.props.label].indexOf(this.filterValue) > -1)
    },
    isAll() {
      if (this.selectValue.length) {
        if (this.filterValue.length) {
          const filterItem = this.filterData.filter((item) => this.selectValue.includes(item[this.props.value]))
          return filterItem.length === this.selectValue.length
        } else {
          return this.filterData.length === this.selectValue.length
        }
      } else {
        return false
      }
    }
  },
  methods: {
    handleAll() {
      if (this.isAll) {
        this.selectValue = []
      } else {
        const data = []
        this.filterData.forEach((item) => data.push(item[this.props.value]))
        this.selectValue = data
      }
      this.handleChange(this.selectValue)
    },
    handleReverseAll() {
      if (this.isAll) {
        this.selectValue = []
      } else {
        const data = []
        this.filterData.forEach((item) => {
          if (!this.selectValue.includes(item[this.props.value])) {
            data.push(item[this.props.value])
          }
        })
        this.selectValue = data
      }
      this.handleChange(this.selectValue)
    },
    handleChange(value) {
      let item
      if ('multiple' in this.$attrs) {
        item = this.selectData.filter((k) => value.includes(k[this.props.value])) || []
      } else {
        item = this.selectData.find((k) => k[this.props.value] === value) || {}
      }
      this.$emit('input', value)
      this.$emit('change', item)
    },
    handleChangeVisible() {
      this.filterValue = ''
    }
  }
}
</script>

<style lang="scss" scoped>
.select-input {
  padding: 5px 8px 5px 5px;
}
.no-mark {
  list-style: none;
}
.select-dropdown {
  .el-select-dropdown__item {
    .the-checkbox {
      display: inline-block;
      position: relative;
      top: 3px;
      border: 1px solid #dcdfe6;
      border-radius: 2px;
      box-sizing: border-box;
      width: 16px;
      height: 16px;
      background-color: #fff;
      z-index: 1;
      margin-right: 5px;
    }
    &.selected {
      &::after {
        display: none;
      }
      .the-checkbox {
        background-color: #07f;
        border-color: #07f;
        &:after {
          position: absolute;
          top: -9px;
          left: 1px;
          font-family: element-icons;
          content: '\e6da';
          font-size: 12px;
          font-weight: 700;
          -webkit-font-smoothing: antialiased;
          color: #fff;
        }
      }
    }
  }
}
.reverse{
  margin-left: 50px;
  font-weight: normal;
  color: #606266 !important;
}
/deep/.scrollbar-wrapper {
  max-height: 168px !important;
}
/deep/.el-select__tags{
  overflow: hidden;
}
</style>

2.使用

<FilterSelectMultiple
   multiple
   v-model="id"
   placeholder="请输入xxx"
   :selectData="nameList"
   :props="{ value: 'id', label: 'name' }"
   clearable
   class="logicSelect"
    @change="handleWarehouseChange"
></FilterSelectMultiple>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值