el-select多选下拉框自定义

5,415 阅读1分钟

elementUI的el-select下拉框多选基础上,自定义下拉框内容,实现品类分组、全选、搜索功能。

先看看效果图 image.png 实现的功能: 1.品类分两级,勾选一级品类,实现二级品类全选和反选; 2.全部品类全选和反选; 3.清空已选品类; 4.搜索品类;

HTML部分:

  <template>
  <el-select 
    multiple 
    collapse-tags 
    v-model="selectNameArr"  
    placeholder="请选择" 
    clearable 
    style="width:280px"
    @change="changeSelectBrand" 
    @remove-tag="removeTag"
    @visible-change="initData"
    popper-class="select-multiple"
  >
    <div class="select-box">
      <el-form :inline="true" class="select-header">
        <el-form-item label="品类选择">
          <el-input
            size="mini"
            v-model="searchValue"
            placeholder="请输入关键词"
            clearable
            @input="searchCat"
            ></el-input>
          </el-form-item>
          <el-form-item>
          <el-button type="primary" size="mini" @click.native="selectAll">全选</el-button>
          <el-button type="warning" size="mini" @click.native="clearAll">清空</el-button>
        </el-form-item>
      </el-form>
      
      <div class="select-content" v-if="!loading">
        <div class="select-item" v-for="(item,index) in catNameOpt" :key="index">
          <div style="margin: 15px 0;font-weight: bold;">
            <el-checkbox v-model="item.checked" @change.native="selectAllCat(item,index)">{{item.label}}</el-checkbox>
          </div>
            <el-option v-for="(subItem,index) in item.children" :key="index" :label="subItem" :value="subItem">
        </el-option>
        </div>
      </div>
      <div class="select-content" v-else>
        <el-option disabled value="暂无数据" label="暂无数据"></el-option>
      </div>
    </div>
  </el-select>
</template>

JS部分:

export default {
  data() {
    return {
      searchValue: '',
      selectNameArr: [],
      catNameOpt: [],
      catList: [],
      loading: false
    }
  },
  methods: {
    initData(val) {
      // 当下拉框显示的时候请求接口
      if(!val) {
        return
      }
      this.getCatMod(this.searchValue ? this.searchValue : '')
    },
    // 获取品类数据
    getCatMod(val) {
      let params = {
        model: val ? val : ''
      }
      this.$api.post('/opinion/getCatMod ',params ,res=>{
        if(res.code=='00'){
          let data = res.returnObject
            this.catNameOpt = data

            if (data.length === 0) {
            // 搜索不到数据时,给个默认选项,不让下拉框收回去
              // console.log(111)
              this.loading = true
              this.catNameOpt = this.catList
              return
            } 

            this.loading = false
            let newArr =  this.catNameOpt.map((item, index) => {
              item =  {
                value: item.category,
                label: item.category,
                children: item.model,
                checked: false
              }
              return item
            });

            this.catNameOpt = newArr
            if (this.catList.length === 0) {
              this.catList = newArr
            }
            
            // console.log('this.catNameOpt',this.catList)
        }
        },err=>{

        })
    },
    dataChange() {
      this.$emit('change', this.selectNameArr)
    },
    // 全选单个品类
    selectSingleCat(item) {
      let newArr = []
      if (item.checked) { // 全选
        // console.log('item.checked',item.checked)
        this.catNameOpt.map((subItem) => {
          if (subItem.value === item.value) {
            newArr = subItem.children
          }
        })
        
      } else {// 反选
              
        let length = item.children.length;
        let start = item.children[0];
        let index = this.selectNameArr.indexOf(start)
        this.selectNameArr.splice(index, length)

        // console.log(start, index, length)
        // console.log('this.selectNameArr',this.selectNameArr)
      }

      return newArr
    },
    // 全选多个品类
    selectAllCat(item) {
      let singleCatArr = this.selectSingleCat(item);
      // console.log('singleCatArr',singleCatArr)

      let newArr = this.selectNameArr.concat(singleCatArr)
      this.selectNameArr = Array.from(new Set(newArr)) // 数组去重
      // console.log('selectNameArr', this.selectNameArr)

      this.dataChange()
    },
    // 全选全部品类
    selectAll() {
      if (this.selectNameArr.length == 0) {
        // 改变checkbox的状态
        this.catNameOpt = this.catNameOpt.map((item) => {
          let newItem = {
            value: item.value,
            label: item.label,
            children: item.children,
            checked: true
          }
          // console.log('newItem',newItem)
          this.selectAllCat(newItem)
          return newItem
        })
      } 
      
    },
    // 选择品类
    changeSelectBrand(val) {
      if ((val.length - 1) < this.catNameOpt.length) {
        this.selectNameArr = this.selectNameArr.filter((item) => {
          return item
        })
      }

      this.dataChange()
      // console.log('this.selectNameArr',this.selectNameArr)
    },
    removeTag(val) {
      this.clearAll()
    },
    // 清空品类
    clearAll() {
      this.selectNameArr = []
      // 改变checkbox的状态
      this.catNameOpt = this.catNameOpt.map((item) => {
        item.checked = false
        return item
      });
      this.dataChange()
      // console.log('selectNameArr', this.selectNameArr)
    },
    // 搜索品类
    searchCat(query) {
      if (query !== '') {
        this.loading = true;
        
        setTimeout(() => {
          this.loading = false;
          this.getCatMod(query)

        }, 200);

      } else {
        this.loading = false;
        this.catNameOpt = this.catList
      }
      // console.log('this.catList',this.catList)
      this.dataChange()
    }
  }
}

css部分:

.select-multiple {
  .select-box {
    padding: 10px;
    .select-item {
      border-bottom: 1px solid #ccc;
      &:last-child{
        border: none;
      }
    }
    .select-header {
      border-bottom: 1px solid #ccc;
    }
    .select-content {
      height: 210px;
      overflow: hidden;
      overflow-y: auto;
    }
    .el-select-dropdown__item {
      width: 30%;
      display: inline-block;
    }
    .el-checkbox {
      width: 100%
    }
  }
}