当前位置:   article > 正文

vue2 el-select 改造成下拉树,支持数据回显_el-tree-select vue 2

el-tree-select vue 2

下拉树 就是一个下拉框里面的options里面换成一棵树的形状。本人业务需要一个这样的组件,我也懒得去发布一个组件到npm库,毕竟现在vue3出来了,这个组件只适合vue2 并且是element ui的基础,限制条件有点多。所以在这里做个笔记,有需要的自己copy 代码到自己本地,就行。

效果

在这里插入图片描述

下面的底色不要在意哈

使用方式

模板文件

 <select-tree
           :value="test"
           :options="options"
           :props="{
            value: 'id', // ID字段名
            label: 'label', // 显示名称
            children: 'children' // 子级字段名
            }"
           :filterable="true"
         />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

数据

看到这个数据,肯定明白,组件已经支持了数据回显。

 test: '1-1',
      // 测试树数据
  options: [
        {
          label: '一级 1',
          id: '1',
          children: [{
            label: '二级 1-1',
            id: '1-1',
            children: [{
              id: '1-1-1',
              label: '三级 1-1-1'
            }]
          }]
        }, {
          label: '一级 2',
          id: '2',
          children: [{
            label: '二级 2-1',
            id: '2-1',
            children: [{
              id: '2-1-1',
              label: '三级 2-1-1'
            }]
          }, {
            id: '2-2',
            label: '二级 2-2',
            children: [{
              id: '2-2-1',
              label: '三级 2-2-1'
            }]
          }]
        }]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

组件代码

组件名称 SelectTree.vue, 如果需要加上disabled 或者个性化的, 自己可以手动添加,代码已经有注释了

<template>
  <div class="tree_select">
    <el-select :value="valueTitle"
               ref="selectEl"
               :filterable="filterable"
               :clearable="clearable"
               @clear="clearHandle"
               :filter-method="selectFilterData"
               :size="size">
      <el-option :value="valueId" :label="valueTitle">
        <el-tree id="tree-option"
                 ref="selectTree"
                 :accordion="accordion"
                 :data="options"
                 :props="props"
                 :node-key="props.value"
                 :expand-on-click-node="false"
                 :default-expanded-keys="defaultExpandedKey"
                 :filter-node-method="filterNode"
                 @node-click="handleNodeClick">
        </el-tree>
      </el-option>
    </el-select>
  </div>
</template>

<script>

export default {
  name: 'SelectTree',
  props: {
    /* 配置项 */
    props: {
      type: Object,
      default: () => {
        return {
          value: 'id', // ID字段名
          label: 'title', // 显示名称
          children: 'children' // 子级字段名
        }
      }
    },
    /* 选项列表数据(树形结构的对象数组) */
    options: {
      type: Array,
      default: () => {
        return []
      }
    },
    /* 初始值 */
    value: {
      type: [Number, String],
      default: () => {
        return null
      }
    },
    /* 可清空选项 */
    clearable: {
      type: Boolean,
      default: () => {
        return true
      }
    },
    /* 自动收起 */
    accordion: {
      type: Boolean,
      default: () => {
        return false
      }
    },
    /**
     * 下拉选项框的大小,默认最小
     */
    size: {
      type: String,
      default: () => {
        return 'mini'
      }
    },
    // 是否可以搜索
    filterable: Boolean
  },
  data () {
    return {
      valueId: this.value, // 初始值
      valueTitle: '',
      defaultExpandedKey: []
    }
  },
  mounted () {
    this.$nextTick(function () {
      this.initHandle()
    })
  },
  methods: {
    // 初始化值
    initHandle () {
      if (this.valueId) {
        this.valueTitle = this.$refs.selectTree.getNode(this.valueId).data[this.props.label] // 初始化显示
        this.$refs.selectTree.setCurrentKey(this.valueId) // 设置默认选中
        this.defaultExpandedKey = [this.valueId] // 设置默认展开
      }
      this.$nextTick(() => {
        const scrollWrap = document.querySelectorAll('.el-scrollbar .el-select-dropdown__wrap')[0]
        const scrollBar = document.querySelectorAll('.el-scrollbar .el-scrollbar__bar')
        scrollWrap.style.cssText = 'margin: 0px; max-height: none; overflow: hidden;'
        scrollBar.forEach(ele => {
          ele.style.width = 0
        })
      })
    },
    // 切换选项
    handleNodeClick (node) {
      this.valueTitle = node[this.props.label]
      this.valueId = node[this.props.value]
      this.$emit('getValue', this.valueId)
      this.defaultExpandedKey = []
      // 选中后失去焦点,隐藏下拉框
      this.$refs.selectEl.blur()
      // 把数据还原
      this.selectFilterData('')
    },
    /**
     * 下拉框搜索
     */
    selectFilterData (val) {
      this.$refs.selectTree.filter(val)
    },
    /**
     * 过滤节点
     */
    filterNode (value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    // 清除选中
    clearHandle () {
      this.valueTitle = ''
      this.valueId = null
      this.defaultExpandedKey = []
      this.clearSelected()
      this.$emit('getValue', null)
    },
    /* 清空选中样式 */
    clearSelected () {
      const allNode = document.querySelectorAll('#tree-option .el-tree-node')
      allNode.forEach((element) => element.classList.remove('is-current'))
    }
  },
  watch: {
    /**
     * 监听绑定的值变化
     */
    value () {
      this.valueId = this.value
      this.initHandle()
    }
  }
}
</script>

<style lang="scss" scoped>
::v-deep .el-select .el-input .el-input__inner {
  color: #fff !important;
}

.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
  height: auto;
  max-height: 274px;
  padding: 0;
  overflow: hidden;
  overflow-y: auto;
}

.el-select-dropdown__item.selected {
  font-weight: normal;
}

ul li > > > .el-tree .el-tree-node__content {
  height: auto;
  padding: 0 20px;
}

::v-deep .el-tree-node__content:hover,
::v-deep .el-tree-node__content:active,
::v-deep .is-current > div:first-child,
::v-deep .el-tree-node__content:focus {
  background-color: #F5F7FA;
  color: #409EFF;
}

</style>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/577711
推荐阅读
相关标签
  

闽ICP备14008679号