elselect + el-tree下拉框 选择(过滤)

大佬们 点赞支持下!!!!

<template>
  <el-select
    ref="elSelect"
    :clearable="clearable"
    :value="selectData.label"
    :disabled="disabled"
    :placeholder="placeholder"
    popper-class="popper-box"
    @clear="clearHandle"
  >
    <el-option style="display: none" value="0" />
    <div v-show="showSearch" class="filter-input" @click.stop>
      <el-input
        v-model.trim="filterText"
        clearable
        size="small"
        placeholder="输入关键字进行过滤"
      />
    </div>
    <el-tree
      ref="selectTree"
      :show-checkbox="multiple"
      :accordion="accordion"
      :check-strictly="checkStrictly"
      :data="dic"
      :lazy="lazy"
      :load="load || treeLoad"
      :props="defaultProps"
      :node-key="defaultProps.value"
      :default-expanded-keys="expandKeys"
      :default-checked-keys="defaultCheckNodes"
      :filter-node-method="filterNode"
      @check="checkHandle"
      @node-click="nodeClickHandle"
    />
  </el-select>
</template>

<script>
export default {
  name: 'ElTreeSelect',
  props: {
    dataCode: {
      type: String,
      default: ''
    },
    dic: {
      type: Array, // 必须是树形结构的对象数组
      default: () => {
        return []
      }
    },
    showSearch: {
      type: Boolean,
      default: true
    },
    // 选项分隔符
    separator: {
      type: String,
      default: ' | '
    },
    placeholder: {
      type: String,
      default: '请选择'
    },
    // 是否显示多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 是否可清除
    clearable: {
      type: Boolean,
      default: false
    },
    // 父子不关联
    checkStrictly: {
      type: Boolean,
      default: true
    },
    lazy: {
      type: Boolean,
      default: false
    },
    load: {
      type: Function,
      default: () => {}
    },
    accordion: {
      type: Boolean,
      default: false
    },
    props: {
      type: Object,
      default: () => {
        return {
          value: 'value', // ID字段名
          label: 'label', // 显示名称
          children: 'children' // 子级字段名
        }
      }
    },

    value: {
      type: [Number, String, Array],
      default: ''
    },
    show: {
      type: Boolean,
      default: true
    },
    disabled: {
      type: Boolean,
      default: false
    },
    defaultCheckNodes: {
      type: Array, // 已经分配的资源
      default: () => {
        return []
      }
    }
  },
  data() {
    return {
      filterText: '',
      selectData: {
        label: '', // 显示文本
        value: this.value, // 初始值
        node: '' // 选中的节点数据
      }
    }
  },
  computed: {
    expandKeys() {
      return Array.isArray(this.value) ? [...this.value] : [this.value]
    },
    defaultProps() {
      if (this.props) {
        const { children, label, value } = this.props
        return {
          children: children || 'children',
          label: label || 'label',
          value: value || 'value'
        }
      }
      return {
        children: 'children',
        label: 'label',
        value: 'value'
      }
    }
  },
  watch: {
    // 关闭弹框清除搜索
    show: {
      handler(n) {
        if (!n) {
          this.filterText = ''
        }
      }
    },
    dic(n) {
      this._setTreeStatus(this.value)
      const selectData = []
      // 获取选中的节点数据
      this._getSelectData(n, selectData)
      this._setLabel(selectData)
    },
    value: {
      handler(n) {
        if (n != this.selectData.value) {
          this.selectData.value = n
          this._initData(n)
        }
      }
    },
    filterText(val) {
      this.$refs.selectTree.filter(val)
    }
  },
  mounted() {
    this._initData(this.value)
  },
  methods: {
    treeLoad() {},
    // 初始化 回显状态和数据
    _initData(n) {
      this.$refs.selectTree.setCurrentKey(null)
      this.$refs.selectTree.setCheckedKeys([])
      this._setTreeStatus(n)
      const selectData = []
      // 获取选中的节点数据
      this._getSelectData(this.dic, selectData)
      this._setLabel(selectData)
    },
    // 根据父id和子id 生成唯一标识 用于id不唯一的数据
    _createUniqueKeyData(arr, parentKeyList = []) {
      const { value, children } = this.defaultProps
      arr.map((item) => {
        item._uniqueKey =
          parentKeyList.join(',') +
          (parentKeyList.length ? `,${item[value]}` : item[value])
        if (item[children] && item[children].length) {
          this._createUniqueKeyData(
            item[children],
            parentKeyList.concat(item[value])
          )
        }
      })
    },
    // 查找已选数据 用于回显label字段
    _getSelectData(data, selectData) {
      const key = this.defaultProps.value
      data.forEach((item) => {
        const isMultipleValue =
          Array.isArray(this.value) && this.value.includes(item[key])
        if (this.value == item[key] || isMultipleValue) {
          selectData.push(item)
        }
        if (item.children && item.children.length) {
          this._getSelectData(item.children, selectData)
        }
      })
    },
    // 设置回显文字
    _setLabel(data) {
      if (data && data.length && this.multiple) {
        this.selectData.label = data
          .map((item) => item[this.defaultProps.label])
          .join(this.separator)
      } else if (data.length && !this.multiple) {
        this.selectData.label = data[0][this.defaultProps.label]
      } else {
        this.selectData.label = ''
      }
    },
    _setTreeStatus(val) {
      this.$nextTick(() => {
        if (!val || (Array.isArray(val) && !val.length)) {
          this.$refs.selectTree.setCurrentKey(null)
          this.$refs.selectTree.setCheckedKeys([])
        } else if (val && !Array.isArray(val)) {
          this.$refs.selectTree.setCurrentKey(val)
        } else if (Array.isArray(val) && val.length) {
          this.$refs.selectTree.setCheckedKeys([...val])
        }
      })
    },
    // 筛选搜索
    filterNode(value, data) {
      if (!value) return true
      return data[this.defaultProps.label].indexOf(value) !== -1
    },
    // 抛出input事件改变父组件绑定值
    modelChange() {
      this.$emit('input', this.selectData.value)
      this.$emit('change', this.selectData.value, this.selectData.node, this.dataCode)
    },
    // 复选框选中
    checkHandle(data, checked) {
      this._setLabel(checked.checkedNodes)
      this.selectData.value = checked.checkedKeys
      this.selectData.node = checked.checkedNodes
      this.modelChange()
      this.$emit('check', data, checked)
    },
    // 点击选中
    nodeClickHandle(data) {
      if (!this.multiple) {
        this.selectData.label = data[this.defaultProps.label]
        this.selectData.value = data[this.defaultProps.value]
        this.selectData.node = data
        this.$refs.elSelect.blur()
        this.modelChange()
        this.$emit('node-click', data)
      }
    },
    // 清除选中
    clearHandle() {
      this.selectData.label = ''
      this.selectData.node = null
      this.selectData.value = ''
      this.$refs.selectTree.setCurrentKey(null)
      if (this.multiple) {
        this.$refs.selectTree.setCheckedKeys([])
      }
      this.modelChange()
    }
  }
}
</script>

<style lang="scss" scoped>
>>> .el-tree-node__content {
  padding: 0 20px;
}
.filter-input {
  width: 100%;
  padding: 10px;
  box-sizing: border-box;
  >>> .el-input__inner {
    height: 28px;
    font-size: 12px;
    line-height: 28px;
  }
}
</style>


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容