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>


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容