带全选项的多选下拉框封装(基于element)

    业务需求期望多选的下拉框带有全部选择选项,并且全部选择选项和其他的选项为互斥关系,而element中的下拉多选框是没有这种全选功能的,所以需要自己实现。下面我们看一下完成的效果动图:

    实现的基本思路就是判断选中项中是否有全部选项,从而对选中项进行过滤。下面是这个多选框组件multi-select.vue的代码:

<template>
    <el-select :placeholder="placeholder" v-model="curOption" filterable :clearable="clearable" multiple :collapse-tags="collapse" :disabled="disabled" :style="{width: width}" @remove-tag="removeTag" @visible-change="$emit('visible-change', $event)" @clear="clear">
        <el-option @click.native="selectOption(item)" v-for="(item, index) in selectList" :key="index" :label="item[opFormat[0]]" :value="item[opFormat[1]]"/>
    </el-select>
</template>
<script>
export default {
    name: 'multi-select',
    props: {
        options: {
          type: Array,
          default: () => []
        },
        opFormat: {
          type: Array,
          default: () => ['label', 'value']
        },
        placeholder: {
          type: String,
          default: '请选择'
        },
        clearable: {
          type: Boolean,
          default: true
        },
        disabled: Boolean,
        width: String,
        collapse: {
          type: Boolean,
          default: true
        },
        alllabel: {
          type: String,
          default: '全部'
        }
    },
    data () {
        return {
            curOption: this.$attrs.value,
            selectList: [],
            allOptions: []
        }
    },
    methods: {
        removeOption (value) {
            let tSet = new Set(this.curOption)
            tSet.delete(value)
            this.curOption = [...tSet]
        },
        removeTag (value) {
            this.removeOption(value)
            this.emitChange(this.curOption)
        },
        clear () {
            this.curOption = []
            this.emitChange([])
        },
        selectOption (value) {
            let v = value[this.opFormat[1]]
            if (!this.curOption.includes(this.alllabel)) return this.emitChange(this.curOption)
            if (v === this.alllabel) {
                this.curOption = [this.alllabel]
                this.emitChange(this.allOptions)
            } else {
                this.removeOption(this.alllabel)
                this.emitChange(this.curOption)
            }
        },
        emitChange ($event) {
            this.$emit('input', [...$event])
            this.$emit('change', [...$event])
        }
    },
    mounted () {
        this.allOptions = this.options.map(i => i[this.opFormat[1]])
        this.selectList = [...this.options]
        this.selectList.unshift({
            [this.opFormat[0]]: this.alllabel,
            [this.opFormat[1]]: '全部'
        })
    }
}
</script>

下拉框数据和组件使用代码分别如下:

data () {
    return {
        point: [],
        pointList: [
            {
                 name: '浙江大学',
                 value: '45'
             },
             {
                 name: '浙理工学',
                 value: '4'
              },
              {
                  name: '青海矿业',
                  value: '34'
               },
               {
                  name: '南海美院',
                  value: '77'
               }
         ]
     }
}
<multi-select v-model="point" :options="pointList" :opFormat="['name', 'value']" multiple :collapse="false" width="350px"/>

 

 这里对组件的两个属性做一下说明:

        1: alllable, 可以指定下拉选项中的全部选项会显示的文案。

        2:opFormat 数组的值依次指定了el-select中的label,value。这样做的意义就是你无法确定数据的key,value对应的属性名时,在封装组件的时候通过一个指定属性去完成原始数据key-value 和组件lable-vlaue的映射关系,也是二次封装的好处,因为我不期望单独去指定key,value,这样的写法比较麻烦。(这就是仁者见仁智者见智了,不习惯这种opFormat的朋友可以自行换成label, value的属性的形式)

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值