Element UI框架中巧用树选择器

先看效果图

树选择器

基本功能

在Element UI框架中有选择器和树形控件,可是没有树形选择器,也就是图上的这种方式的选择器,因此只能自定义选择器的slot。这里介绍的是多选状况,若是是单选则去掉复选框,修改一部分的处理便可。html

html部分的代码:node

<el-select
    v-model="dataArr"
    :multiple="multiple"
    filterable
    :placeholder="placeholder"
    :disabled="disabled"
    :collapse-tags="multiple"
    @remove-tag="handleTagChange"
    @visible-change="handleOptionHidden"
    class="hi-input">
    <el-option value="0"
        class="hidden">
    </el-option>
    <!--el-tree绑定的数组中children里的key值不能是0-->
    <el-tree
        ref="tree"
        :data="options"
        node-key="key"
        show-checkbox
        :default-checked-keys="selectedData"
        @check="handleCheckChange"
        :props="defaultProps">
    </el-tree>
</el-select>
复制代码

树形控件到选择器的绑定

在el-tree中绑定的值是已选择的key值组成的数组,check绑定的事件函数是为了:数组

  • 获得如今树选择器上选中的值
  • 过滤undefined、null的值(是为了容错处理) 具体代码以下:
handleCheckChange: function() {
    this.selectedData = this.$refs.tree.getCheckedKeys().filter(_ => _);
}
复制代码

由于选择器是有label值和key值区分的,因此,每当在el-tree中选中值key值变化时,选择器上绑定的值label值也应该随之变化,因此在watch中监听key值,目的是在el-tree绑定的data中找到当前key值对应的label值 具体代码以下:bash

watch: {
    selectedData: function(newValue) {
        this.$nextTick(() => { this.dataArr = this.handleDataTransform(newValue, 'key', 'label'); });
    },
},
methods: {
    getNameById(array, value, id, name, multi) {
        let arr = array || [];
        let flag;
        let result = arr.filter(item => {
            return item[id] + '' === value + '';
        });
        if (multi) {
            flag = result.map(item => {
                return item[name];
            });
        } else {
            let obj = result[0];
            flag = name ? obj && obj[name] : obj;
        }
        return flag;
    },
    handleDataTransform: function(source, key, value) {
        return this.options.map(_ => {
            let arr = source.map(item => this.getNameById(
                _.children,
                item,
                key,
                value
            )).filter(item => item);
            return arr;
        }).reduce((acc, cur) => {
            return acc.concat(cur);
        }, []);
    }
}
复制代码

到这里为止,已经完成了树形控件到选择器的单向绑定框架

选择器到树形控件的绑定

remove-tag事件

如今处理选择器的值发生改变时,树形控件也变化。由于此时是多选,因此要在remove-tag事件中处理,具体代码以下:函数

handleTagChange: function() {
    //  handleDataTransform已经在以前定义过
    this.selectedData = this.handleDataTransform(this.dataArr, 'label', 'key');
    this.$refs.tree.setCheckedKeys(this.selectedData);
},
复制代码

change事件

经过测试发现,当在键盘上点击delete时,也会删除选择器内选中的元素,我尝试过绑定@keyup.delete事件,可是绑定不成功,若是使用了.native修饰符能够监听到事件了,可是阻止了原生删除事件,因此也不可取。通过测试发现绑定change事件就能够处理键盘的delete事件,绑定的函数和handleTagChange同样。测试

优化

此时,这个树形选择器已经完成了~👏👏,可是,咱们还能够进一步优化,好比优化

选择项不变,不重复发请求

若是选择后的内容与选择前的内容同样,再也不发生请求的处理。 在选择器中绑定的visible-change事件能够处理,思想是:ui

  1. item值为true,即展开下拉框时,把此时的值存储下来,注意⚠️:这时候存储下来的值必须放在一个全局变量中,函数内的变量会在每次进入这个函数时初始化,因此在下拉框收起再进来这个函数时,以前存储的值已经没有了。
  2. item值为false,即收起下拉框时,判断以前存储下的变量值和当前变量值是否相等,若是不相等才触发数据的更新。 具体代码以下:
handleOptionHidden: function(item) {
    // 处理选中内容没变的状况
    if (item) {
        this.selectedItem = [...this.selectedData];
    } else {
        //  this.$util.isEqual()是判断两个数组是否相等函数,网上不少,请自行谷歌
        if (!this.$util.isEqual(this.selectedItem, this.selectedData)) {
            this.handleUpdate(this.selectedData);
        }
    }
}
复制代码

选择器的搜索功能

当数据量大的时候,选择器通常都会有搜索的需求,在选择器上封装过的搜索功能没法知足需求,由于树形控件自己有搜索的函数,因此在选择器上自定义filter-mothod事件,调用树形控件的搜索事件便可。this

handleSelectFilter: function(val) {
    this.$refs.tree.filter(val);
},
复制代码

在树形控件上绑定filter-node-method自定义函数,支持忽略大小写搜索

handleTreeFilter: function(value, data) {
    if (!value) return true;
    return data.label.toUpperCase().indexOf(value.toUpperCase()) !== -1;
},
复制代码

以上就是所有内容了,若是哪里写的差点意思,请告诉我哈~记得点赞👍,thanks~

相关文章
相关标签/搜索