ElementUI el-select 自定义下拉树

下拉树单选

<el-select
    v-model="selectModel"
    placeholder="请选择..."
    size="small"
    clearable
    filterable
    :filter-method="singleTreeFilterMethod"
    ref="select"
    popper-class="customSelectPopper"
    @focus="singleTreeFocus"
    @clear="singleTreeClear">
    <el-option
        v-for="item of selectOptions"
        :key="item.id"
        :label="item.label"
        :value="item.id"
        v-show="false">
    </el-option>
    <div class="singleTree">
        <el-tree
            :data="selectTreeData"
            ref="selectTree"
            node-key="id"
            empty-text="无匹配数据"
            highlight-current
            :expand-on-click-node="expandOnClickNode" // 是否在点击节点的时候展开或者收缩节点
            :default-expanded-keys="defaultExpandedkeys" // 默认展开的节点的 key 的数组
            :props="{'label': 'label', children: 'children', disabled: 'disabled', isLeaf: 'isLeaf'}"
            :filter-node-method="filterNode"
            @node-click="selectTreeNodeClickEvent">
        </el-tree>
    </div>
</el-select>

data(){
    return {
        selectModel: '',
        selectOptions: [],
        selectTreeData: [{
            id: '1',
            label: '一级 1',
            isLeaf: false,
            children: [{
                id: '1-1',
                label: '二级 1-1',
                isLeaf: false,
                children: [{
                    id: '1-1-1',
                    label: '三级 1-1-1',
                    isLeaf: true
                }]
            }]
        }, {
            id: '2',
            label: '一级 2',
            isLeaf: false,
            children: [{
                id: '2-1',
                label: '二级 2-1',
                isLeaf: false,
                children: [{
                    id: '2-1-1',
                    label: '三级 2-1-1',
                    isLeaf: true
                }]
            }, {
                id: '2-2',
                label: '二级 2-2',
                isLeaf: false,
                children: [{
                    id: '2-2-1',
                    label: '三级 2-2-1',
                    isLeaf: true
                }]
            }]
        }, {
            id: '3',
            label: '一级 3',
            isLeaf: false,
            children: [{
                id: '3-1',
                label: '二级 3-1',
                isLeaf: false,
                children: [{
                    id: '3-1-1',
                    label: '三级 3-1-1',
                    isLeaf: true
                }]
            }, {
                id: '3-2',
                label: '二级 3-2',
                isLeaf: false,
                children: [{
                    id: '3-2-1',
                    label: '三级 3-2-1',
                    isLeaf: true
                }]
            }]
        }],
        expandOnClickNode: false,
        defaultExpandedkeys: []
    }
},
methods:{
    /**
     * select 单选下拉树自定义搜索
     * @param {Object} val
     */
    singleTreeFilterMethod(val){
        this.$refs.selectTree.filter(val);
    },
    /**
     * select 获取焦点事件
     */
    singleTreeFocus(){
        this.$refs.selectTree.filter("");
    },
    /**
     * tree 节点过滤
     * @param {Object} value
     * @param {Object} data
     */
    filterNode(value, data) {
        if (!value) return true;
        return data.label.indexOf(value) !== -1;
    },
    /**
     * tree 节点点击事件
     * @param {Object} data
     */
    selectTreeNodeClickEvent(data){
        if(this.expandOnClickNode){ // 只有叶子节点可被选择
            if(data.isLeaf && data.isLeaf == true){
                this.selectModel = data.id; // select v-model 赋值
                this.selectOptions = [data]; // 隐藏的 select option 赋值
                this.$refs.select.blur(); // 收起 select 下拉框
            }
        }else{ // 任意节点可被选择
            this.selectModel = data.id; // select v-model 赋值
            this.selectOptions = [data]; // 隐藏的 select option 赋值
            this.$refs.select.blur(); // 收起 select 下拉框
        }
    },
    /**
     * select 清空按钮点击事件
     */
    singleTreeClear(){
        // do something
    },
    /**
     * 回显数据
     */
    echoData(){
        let data = 请求接口返回值;

        // select v-model 赋值
        this.selectModel = data.id;
        // 隐藏的 select option 赋值
        this.selectOptions = [{
            id: data.id,
            label: data.label
        }];

        this.defaultExpandedkeys = [data.id]; // 展开选中的节点
        this.$refs.selectTree.setCurrentKey(data.id); // 设置节点高亮

        // 无法使用 current-node-key(当前选中的节点) 属性,如果在 data 里定义初始值,可以实现该 id 对应节点的默认选中高亮效果
        // 但如果用 this.currentNodeKey = xx 再修改这个值,没有任何变化
    }
}

下拉树多选

<el-select
    v-model="selectModel"
    placeholder="请选择..."
    multiple
    size="small"
    clearable
    ref="select"
    class="selectMultiple"
    popper-class="customSelectPopper"
    @remove-tag="removeTag"
    @clear="multipleTreeClear">
    <el-option
        v-for="item of selectOptions"
        :key="item.id"
        :label="item.label"
        :value="item.id"
        v-show="false">
    </el-option>
    <div class="multipleTree">
        <!-- 当 el-select 在 el-form 表单中,并且属于必填项,添加 el-form-item 标签 以便解决 在搜索 input 中输入时执行 el-select 验证 -->
        <el-form-item style="margin-bottom: 0;" v-if="inForm">
            <el-input v-model="selectTreeNodeFilterText" size="small" placeholder="请输入关键字搜索" class="filterInp"></el-input>
        </el-form-item>
        <el-input v-else v-model="selectTreeNodeFilterText" size="small" placeholder="请输入关键字搜索" class="filterInp"></el-input>
        <div class="treeWrapper">
            <el-scrollbar class="commonScrollbar">
                <el-tree
                    :data="selectTreeData"
                    show-checkbox
                    ref="selectTree"
                    node-key="id"
                    empty-text="无匹配数据"
                    :default-expanded-keys="defaultExpandedkeys" //  默认展开的节点的 key 的数组
                    :default-checked-keys="defaultCheckedKeys" // 默认勾选的节点的 key 的数组
                    :props="{'label': 'label', children: 'children', disabled: 'disabled', isLeaf: 'isLeaf'}"
                    :filter-node-method="filterNode"
                    @check="selectTreeNodeCheckEvent">
                </el-tree>
            </el-scrollbar>
        </div>
    </div>
</el-select>
data(){
    return {
        inForm: false,
        selectModel: [],
        selectOptions: [],
        selectTreeData: [{
            id: '1',
            label: '一级 1',
            isLeaf: false,
            children: [{
                id: '1-1',
                label: '二级 1-1',
                isLeaf: false,
                children: [{
                    id: '1-1-1',
                    label: '三级 1-1-1',
                    isLeaf: true
                }]
            }]
        }, {
            id: '2',
            label: '一级 2',
            isLeaf: false,
            children: [{
                id: '2-1',
                label: '二级 2-1',
                isLeaf: false,
                children: [{
                    id: '2-1-1',
                    label: '三级 2-1-1',
                    isLeaf: true
                }]
            }, {
                id: '2-2',
                label: '二级 2-2',
                isLeaf: false,
                children: [{
                    id: '2-2-1',
                    label: '三级 2-2-1',
                    isLeaf: true
                }]
            }]
        }, {
            id: '3',
            label: '一级 3',
            isLeaf: false,
            children: [{
                id: '3-1',
                label: '二级 3-1',
                isLeaf: false,
                children: [{
                    id: '3-1-1',
                    label: '三级 3-1-1',
                    isLeaf: true
                }]
            }, {
                id: '3-2',
                label: '二级 3-2',
                isLeaf: false,
                children: [{
                    id: '3-2-1',
                    label: '三级 3-2-1',
                    isLeaf: true
                }]
            }]
        }],
        defaultExpandedkeys: [],
        defaultCheckedKeys: [],
        selectTreeNodeFilterText: ''
    }
},
watch: {
    selectTreeNodeFilterText(val) {
        this.$refs.selectTree.filter(val);
    }
},
methods:{
    /**
     * tree 节点过滤
     * @param {Object} value
     * @param {Object} data
     */
    filterNode(value, data) {
        if (!value) return true;
        return data.label.indexOf(value) !== -1;
    },
    /**
     * tree 节点 check 事件(当复选框被点击的时候触发)
     * @param {Object} currentNodeObj 传递给 data 属性的数组中该节点所对应的对象
     * @param {Object} treeCheckNodeObj 树目前的选中状态对象
     */
    selectTreeNodeCheckEvent(currentNodeObj, treeCheckNodeObj){
        // 获取所有选中的节点 key 并给 select v-model 赋值
        this.selectModel = treeCheckNodeObj.checkedKeys;
        // 获取所有选中的节点对象 并给 隐藏的 select option 赋值
        this.selectOptions = treeCheckNodeObj.checkedNodes;
    },
    /**
     * 多选模式下移除 tag 事件
     * @param {Object} tag 当前 tag 对象
     */
    removeTag(data){
        // 获取所有选中的节点对象
        let checkNode = this.$refs.selectTree.getCheckedNodes(true);

        // 删除节点
        for(let i = 0; i < checkNode.length; i++){
            if(checkNode.id == data.id){
                checkNode.splice(i, 1);
                break;
            }
        }

        // 设置 tree 选中的节点
        this.$refs.selectTree.setCheckedNodes(checkNode);
    },
    /**
     * 点击清空按钮时触发
     */
    multipleTreeClear(){
        this.$refs.selectTree.setCheckedNodes([]);
    },
    /**
     * 回显数据
     */
    echoData(){
        let data = 请求接口返回值;

        // select v-model 赋值
        this.selectModel = data.ids;
        // 隐藏的 select option 赋值
        for(let i = 0; i < data.ids.length; i++){
            this.selectOptions.push({
                id: data.ids[i],
                label: data.label[i]
            });
        }

        this.defaultExpandedkeys = data.ids; // 展开选中的节点

        this.$refs.selectTree.setCheckedKeys(data.ids); // 默认选中的节点
        // 或者
        this.defaultCheckedKeys = data.ids; // 默认选中的节点
    }
}

css

<style lang="scss" scoped>
    /* 自定义 select 下拉 公共样式 */
    .customSelectPopper{
        .el-scrollbar{
            display: block !important;
            .el-scrollbar__wrap{
                max-height: 317px;
                .el-scrollbar__view{
                    .el-select-dropdown__item{
                        display: none;
                    }
                    // 自定义下拉树-----单选
                    .singleTree{
                        .el-tree__empty-block{
                            padding: 4px 0;
                            font-size: 14px;
                            min-height: 14px;
                            height: 14px;
                            .el-tree__empty-text{
                                color: #999;
                            }
                        }
                    }
                    // 自定义下拉树-----多选
                    .multipleTree{
                        .filterInp{
                            width: calc(100% - 40px);
                            display: block;
                            margin: 0 auto;
                        }
                        .treeWrapper{
                            padding: 10px 0;
                            height: 207px;
                            box-sizing: border-box;
                            .el-tree__empty-block{
                                padding: 4px 0;
                                font-size: 14px;
                                min-height: 14px;
                                height: 14px;
                                .el-tree__empty-text{
                                    color: #999;
                                }
                            }
                            .el-scrollbar{
                                .el-scrollbar__bar{
                                    z-index: 2;
                                }
                            }
                        }
                    }
                }
            }
            &.is-empty{
                .el-scrollbar__wrap{
                    .el-scrollbar__view{
                        padding: 6px 0;
                    }
                }
            }
        }
        // 隐藏 select 空数据提示
        .el-select-dropdown__empty{
            display: none;
        }
    }


    /* 下拉多选 公共样式 */
    .selectMultiple{
        .el-select__tags{
            &>span{
                display: block;
                width: 100%;
                overflow-x: auto;
                overflow-y: hidden;
                white-space: nowrap;
                margin-left: 2px;
                .el-tag{
                    display: inline-block;
                }
                &::-webkit-scrollbar{
                    width: 0;
                    height: 0;
                }
            }
        }
        &.noneClose{
            .el-select__tags{
                .el-tag{
                    .el-tag__close{
                        display: none;
                    }
                }
            }
        }
    }

    /* 全局设置el-scrollbar高度 */
    .commonScrollbar.el-scrollbar{
        height: 100%;
    }
    /* 全局隐藏el-scrollbar横向滚动条 */
    .commonScrollbar.el-scrollbar .el-scrollbar__wrap{
        overflow-x: hidden;
    }
    /* 全局设置子容器高度 */
    // .commonScrollbar.el-scrollbar .el-scrollbar__wrap .el-scrollbar__view{
    //    height: 100%;
    // }
</style>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容