基于iview封装的定制化select下拉菜单

基于iview封装的定制化select下拉菜单

前天PM那边给了个UE图,上面有这么个需求:
在这里插入图片描述
在这里插入图片描述

  • iview没有内置的这种类型的组件,因此,自己着手封了一个(一言不合就封它!)

  • 而且select在该需求的基础上增加了一些功能:

     1. 是否需要默认状态下自动显示全选
     2. select宽度自定义
     3. 支持父组件v-if下的显示隐藏该select子组件
    

完成效果如下:

在这里插入图片描述
代码如下:

<template>
    <!-- 定制下拉菜单组件 & 开放搜索、多选功能 -->
    <div class="search-select-tepl">
        <span v-if="dataList.showTitle ? true : false">{{ dataList.title ? dataList.title : '请选择' }}</span>
        <Select @on-open-change="handleProduct()"
                :placeholder="dataList.placeholder ? dataList.placeholder : '全部'"
                clearable
                size="small"
                :style="'width:'+ width + 'px;'">
            <Input v-if="dataList.showSearch" style="width: 190px;"
                   size="small"
                   icon="ios-search"
                   :placeholder="dataList.searchPlaceHolder ? dataList.searchPlaceHolder : '请输入内容回车搜索'"
                   v-model="dataList.search"
                   @input="searchProduct">
            </Input>
            <Checkbox
                    class="check-all"
                    :indeterminate="dataList.indeterminate"
                    :value="dataList.checkAll"
                    @click.prevent.native="handleCheckAll()">{{ dataList.checkAllName ? dataList.checkAllName : '全选' }}</Checkbox>
            <CheckboxGroup @on-change="handleCheck()" v-model="dataList.checkList">
                <Checkbox class="check-option" v-for="(item, index) in dataList.datalist" :key="index" :label="item.value">{{ item.label }}</Checkbox>
            </CheckboxGroup>
        </Select>
    </div>
</template>

<script>
    export default {
        name: "searchSelectTepl",
        props: ['list'],
        data() {
            return {
                dataList: Object.assign({}, this.list)
            }
        },
        watch: {
            'dataList': {
                handler(val, oldValue) {
                    for(let item in val) {
                        if (this.dataList.checkList.length === this.dataList.datalist.length) {
                            this.dataList.placeholder = "全部";
                        } else if (this.dataList.checkList.length == 0) {
                            this.dataList.placeholder = "请选择";
                        } else if (this.dataList.checkList.length > 0) {
                            this.dataList.placeholder = "已选" + this.dataList.checkList.length + "项";
                        }
                    }
                },
                deep:true
            },
        },
        computed: {
            // width
            width() {
                if (this.dataList.width) {
                    return this.dataList.width;
                } else {
                    return 120;
                }
            },
        },
        created() {
            this.dataList.datalistInfo = this.dataList.datalist;
            // 匹配父组件 v-if时 默认全部
            if ((!this.dataList.checkList.length) && this.dataList.showCheckAll) {
                this.handleCheckSelect();
            }
        },
        methods: {
            // 初始化下拉菜单数据
            handleCheckSelect() {
                this.dataList.checkList = [];
                this.dataList.datalist.map(item => {
                    this.dataList.checkList.push(item.value);
                })
            },
            // select 展开 & 收起事件
            handleProduct() {
                if (this.dataList.showCheckAll) {
                    if (!this.dataList.checkList.length) {
                        this.handleCheckSelect();
                        this.dataList.indeterminate = false;
                        this.dataList.checkAll = true;
                    }
                }
                // 菜单关闭执行回调
                this.$emit('sendCheckList', this.dataList);
            },
            // 产品线下拉菜单 & 搜索
            searchProduct() {
                this.dataList.datalist = this.dataList.datalistInfo;
                if (this.dataList.search && this.dataList.search!= '') {
                    let tempProductLineList = [];
                    this.dataList.datalist.forEach(item => {
                        if (item.label.match(this.dataList.search)) {
                            tempProductLineList.push(item);
                        }
                    })
                    this.dataList.datalist = tempProductLineList;
                }
            },
            // 全选check
            handleCheckAll() {
                if (this.dataList.indeterminate) {
                    this.dataList.checkAll = false;
                } else {
                    this.dataList.checkAll = !this.dataList.checkAll;
                }
                this.dataList.indeterminate = false;

                if (this.dataList.checkAll) {
                    this.handleCheckSelect();
                } else {
                    this.dataList.checkList = [];
                }
                this.$emit('sendCheckList', this.dataList);
            },
            // check某一项
            handleCheck() {
                let data = this.dataList.checkList;
                if (data.length === this.dataList.datalist.length) {
                    this.dataList.indeterminate = false;
                    this.dataList.checkAll = true;
                } else if (data.length > 0) {
                    this.dataList.indeterminate = true;
                    this.dataList.checkAll = false;
                } else {
                    this.dataList.indeterminate = false;
                    this.dataList.checkAll = false;
                }
                this.$emit('sendCheckList', this.dataList);
            },
            // 同步数据
            setDataList(val) {
                this.dataList = val;
            }
        }
    }
</script>

<style lang="less">
    .search-select-tepl {
        position: relative;
        /* 定制下拉菜单样式 */
        .ivu-select-dropdown {
            width: 210px;
        }
        .check-all {
            margin: 5px 5px 0 5px;
        }
        /* 多选checkGroup */
        .ivu-checkbox-group {
            max-height: 140px;
            overflow: auto;
            padding: 5px 5px;
            .check-option {
                float: left;
                width: 100%;
                line-height: 20px;
            }
        }
        .ivu-select-dropdown {
            padding: 5px;
        }
    }
</style>

1. dataList模板说明、字段含义:

  1. sendCheckList()函数表示checked之后,checkList数据(选择的数据),需要父组件中函数接收这个数据。例如在父组件中:
    在这里插入图片描述
  2. 下面dataList对象中各个属性表示该组件各项配置。例如:showCheckAll:,表示默认状态下全选。
// 使用模板  属性
// sendCheckList()  this.$emit('sendCheckList', this.dataList);  // 同步父组件checkList数据
dataList: {
    key: 'runTime', // 标识
    title: '执行周期',  // 标题  默认为'请选择'
    showTitle: true,  // 是否显示标题   默认为true
    placeholder: '全部', // 默认状态
    search: '',  // 搜索
    width: 140,  // select宽  默认为120px
    showSearch: true,  // 是否显示搜索
    searchPlaceHolder: '请输入执行周期进行搜索',  // search placeholder  默认为'请输入内容回车搜索'
    indeterminate: false,  // 是否处于半选状态
    checkAllName: '全选',  默认为'全选'
    checkAll: true,  // 是否默认全选
    showCheckAll: '', // 是否需要自动匹配全选
    checkList: [],  // checked list
    datalistInfo: [],  // 临时存储
    datalist: [  // 下拉菜单项
        {
            value: '1',
            label: '苹果'
        }
    ]
}

2. 父组件传递子组件dataList格式,就是上方属性datalist格式
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值