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="輸入關(guān)鍵字進行過濾"
      />
    </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, // 必須是樹形結(jié)構(gòu)的對象數(shù)組
      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
    },
    // 父子不關(guān)聯(lián)
    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, // 已經(jīng)分配的資源
      default: () => {
        return []
      }
    }
  },
  data() {
    return {
      filterText: '',
      selectData: {
        label: '', // 顯示文本
        value: this.value, // 初始值
        node: '' // 選中的節(jié)點數(shù)據(jù)
      }
    }
  },
  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: {
    // 關(guān)閉彈框清除搜索
    show: {
      handler(n) {
        if (!n) {
          this.filterText = ''
        }
      }
    },
    dic(n) {
      this._setTreeStatus(this.value)
      const selectData = []
      // 獲取選中的節(jié)點數(shù)據(jù)
      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() {},
    // 初始化 回顯狀態(tài)和數(shù)據(jù)
    _initData(n) {
      this.$refs.selectTree.setCurrentKey(null)
      this.$refs.selectTree.setCheckedKeys([])
      this._setTreeStatus(n)
      const selectData = []
      // 獲取選中的節(jié)點數(shù)據(jù)
      this._getSelectData(this.dic, selectData)
      this._setLabel(selectData)
    },
    // 根據(jù)父id和子id 生成唯一標識 用于id不唯一的數(shù)據(jù)
    _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])
          )
        }
      })
    },
    // 查找已選數(shù)據(jù) 用于回顯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)
        }
      })
    },
    // 設(shè)置回顯文字
    _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)
    },
    // 復(fù)選框選中
    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>


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容