• el-select+el-tree仿TreeSelect组件


    <!--el-select+el-tree -->
    <template>
      <el-select
        ref="select"
        popper-class="TREE_SELECT_POPPER"
        :value="showLabel"
        :size="size"
        :placeholder="placeholder"
        :clearable="clearable"
        :disabled="disabled"
        :filterable="filterable"
        :filter-method="selectFilter"
        @visible-change="visibleChange"
        @focus="selectFocus"
        @clear="emitVal"
      >
        <el-option class="option_li" :value="showLabel" :label="showLabel" :style="{height: optionHeight+'px'}">
          <el-scrollbar class="option_li_scroll">
            <el-tree
              ref="tree"
              :accordion="accordion"
              :data="options"
              :props="props"
              :node-key="props.value"
              :show-checkbox="multiple"
              :default-expanded-keys="(multiple && Array.isArray(value)) ? value : [value]"
              :default-checked-keys="(multiple && Array.isArray(value)) ? value : []"
              :expand-on-click-node="false"
              :check-strictly="checkStrictly"
              :filter-node-method="treeFilter"
              @node-click="nodeClick"
              @check="nodeCheck"
            />
          </el-scrollbar>
        </el-option>
      </el-select>
    </template>
    <script>
    import pinyinMatch from 'pinyin-match'
    export default {
      name: 'TreeSelect',
      props: {
        props: { // 配置项
          type: Object,
          default() {
            return {
              value: 'value',
              label: 'label',
              children: 'children'
            }
          }
        },
        options: { // 选项列表数据
          type: Array,
          default() {
            return []
          }
        },
        value: { // 绑定值
          type: [String, Number, Array],
          default: ''
        },
        accordion: { // 是否每次只展开一个同级树节点
          type: Boolean,
          default: false
        },
        size: {
          type: String,
          default: ''
        },
        multiple: { // 是否可多选
          type: Boolean,
          default: false
        },
        filterable: { // 是否可搜索
          type: Boolean,
          default: true
        },
        clearable: { // 是否可清空
          type: Boolean,
          default: true
        },
        disabled: { // 是否禁用
          type: Boolean,
          default: false
        },
        placeholder: {
          type: String,
          default: ''
        },
        checkStrictly: { // 父子是否不互相关联
          type: Boolean,
          default: false
        },
        lastLevel: {
          type: String,
          default: ''
        },
        infoError: {
          type: String,
          default: ''
        },
        popHeight: {
          type: [String, Number],
          default: 247
        }
      },
      data() {
        return {
          optionHeight: 247
        }
      },
      computed: {
        showLabel() {
          let label = ''
          const value = this.value
          if (this.multiple) { // 多选
            if (Array.isArray(value) && value.length > 0) {
              const labelArr = []
              value.forEach(value => {
                labelArr.push(this.queryTree(this.options, value))
              })
              label = labelArr.join(',')
            }
          } else { // 单选
            if (value) {
              label = this.queryTree(this.options, value)
            }
          }
          return label
        }
      },
      methods: {
        // 搜索树状数据中的 ID,获取label
        queryTree(tree, id) {
          let stark = []
          stark = stark.concat(tree)
          let label = ''
          while (stark.length) {
            const temp = stark.shift()
            if (temp[this.props.children]) {
              stark = stark.concat(temp[this.props.children])
            }
            if (temp[this.props.value] === id) {
              label = temp[this.props.label]
            }
          }
          return label
        },
        // 提交值
        emitVal(val) {
          if (!val) {
            val = this.multiple ? [] : ''
          }
          this.$emit('input', val)
        },
        // select框获得焦点
        selectFocus() {
          this.$refs.tree.filter('')
          this.$emit('on-focus')
        },
        // select option过滤
        selectFilter(label) {
          this.$refs.tree.filter(label)
          return true
        },
        // 树过滤方法
        treeFilter(query, data) {
          if (!query) {
            return true
          } else {
            const labelArray = query.split(',')
            // 拼配全有科室 误删
            // return labelArray.some(value => {
            //   return value && data[this.props.label].includes(value)
            // })
            return labelArray.some(value => {
              return value && pinyinMatch.match(data[this.props.label], value)
            })
          }
        },
        // 下拉框出现/隐藏
        visibleChange(show) {
          if (show) {
            this.$nextTick(() => {
              const tree_H = this.$refs.tree.$el.clientHeight
              if (tree_H < this.optionHeight) {
                this.optionHeight = this.popHeight
              }
            })
          }
        },
        // 点击节点
        nodeClick(node) {
          if (!this.multiple) {
            if (node[this.lastLevel] === 0) {
              this.$message.error(this.infoError)
              this.emitVal()
              return false
            }
            this.emitVal(node[this.props.value])
            this.$emit('info', node)
            this.$refs.select.blur() // 使select失去焦点 隐藏下拉框
          }
        },
        // 点击复选框
        nodeCheck(node, data) {
          this.emitVal(data.checkedKeys)
        }
      }
    }
    </script>
    <style lang="scss" type="text/scss">
      .TREE_SELECT_POPPER>.el-scrollbar {
        >.el-scrollbar__bar.is-vertical {
          right:10px;
          display: none;
        }
      }
      .TREE_SELECT_POPPER .el-select-dropdown__item{
        background: #fff;
      }
    </style>
    <style scoped lang="scss" type="text/scss">
      .el-select-dropdown__item {
        height: auto;
        padding: 0;
        &.selected {
          font-weight: normal;
        }
      }
      .el-tree /deep/ .el-tree-node__content {
        height: 34px !important;
        padding: 0 10px 0 0;
      }
      .option_li {
        padding: 0;
        background-color: #fff;
        &.selected {
          font-weight: normal;
        }
        .option_li_scroll {
          height: 100%;
          /deep/ .el-scrollbar__wrap{
            overflow-x: hidden;
          }
        }
      }
      .el-tree {
        box-sizing: border-box;
        padding: 0 12px;
      }
    </style>
     
    使用
    <tree-select
          v-model="departValue"
          :options="departmentList"
          :props="{
            label: 'treedatacodeandname',
            value: treeValue,
            children: 'childList'
          }"
          :disabled="disabled"
          filterable
          last-level="blnisdetail"
          info-error="请选择末级"
          @input="onChange"
          @info="onChangeInfo"
        />
  • 相关阅读:
    比较器 Comparable 与compartor 的区别及理解
    事务特性、事务隔离级别、spring事务传播特性
    分布式文件上传-FastDFS
    spring-cloud 组件总结以及搭建图示 (六)
    springCloud zuul网关(五)
    hashCode与equals 通过面试题一窥究竟
    【原】那年30岁
    【原】Hyper-V虚拟机设置外部网络访问
    【原】win10 .net framework 3.5安装
    【原】做梦有感
  • 原文地址:https://www.cnblogs.com/hellofangfang/p/13219921.html
Copyright © 2020-2023  润新知