vue + elementUI 实现下拉树形结构选择部门,支持多选,支持检索

vue + elementUI 实现下拉树形结构选择部门,支持多选,支持检索

javascript 复制代码
<template>
  <div>
    <el-select v-model="multiple?choosedValue:choosedValue[0]" element-loading-background="rgba(0,0,0,0.8)"
               :disabled="disableFlag" @visible-change="visibleChange"
               filterable clearable collapse-tags :filter-method="filterMethod" @clear="clear" @remove-tag="removeTag"
               :multiple="multiple" ref="selectRef" v-loading="loading" style="width: 100%">
      <el-option :label="option.name" :value="option.id" v-for="option in options" :key="option.id"
                 class="optionClass"/>
      <template v-slot:empty>
        <div/>
      </template>
      <el-tree :props="treeProps" :load="loadNode" :data="treeData" :show-checkbox="multiple" @check="handleCheck"
               :expand-on-click-node="false" @node-click="chooseNode" :filter-node-method="filterNodeMethod"
               class="treeClass" ref="treeRef" :node-key="'id'" :default-checked-keys="choosedValue"/>
    </el-select>
  </div>
</template>

<script>
import {getDwxxOfTree} from "@/api/commentTable/api";

export default {
  name: "chooseUnitTree",
  props: {
    disableFlag: {
      Type: Boolean,
      required: false,
      default: false
    },
    value: {
      Type: Object,
      required: true
    },
    multiple: {
      Type: Boolean,
      required: false,
      default: false
    }
  },
  data() {
    return {
      treeProps: {
        label: 'name',
        value: 'id',
        children: 'children'
      },
      deptMap: {},
      treeData: [],
      options: [],
      loading: false,
      choosedValue: [],
      choosedOptions: [],
    }
  },
  computed: {},
  watch: {
    // choosedValue: {
    //   handler(n, o) {
    //     if (this.$refs.treeRef) {
    //       this.$refs.treeRef.filter()
    //     }
    //   },
    //   immediate: true,
    //   deep: true
    // }
  },
  mounted() {
    this.choosedValue = []
    this.getNodeData()
  },
  methods: {
    visibleChange(visible) {
      if (!visible) {
        this.$refs.treeRef.filter()
      }
    },
    removeTag(nodeId) {
      this.choosedValue = this.choosedValue.filter(item => item !== nodeId)
      this.choosedOptions = this.choosedOptions.filter(item => item.id !== nodeId)
      this.$refs.treeRef.setCheckedKeys(this.choosedValue, false)
      this.$emit('input', this.multiple ? this.choosedValue : this.choosedValue[0])
    },
    clear() {
      this.choosedValue = []
      this.choosedOptions = []
      this.$refs.treeRef.setCheckedKeys([], false)
      this.$emit('input', '')
    },
    filterMethod(keyWord) {
      this.$refs.treeRef.filter(keyWord)
    },
    filterNodeMethod(keyWord, node) {
      if (!keyWord) {
        return true
      }
      return (node.name + node.id).includes(keyWord)
    },
    init() {
      this.choosedValue = []
      if (typeof this.value === 'string') {
        this.choosedOptions.push(this.deptMap[this.value])
        this.choosedValue.push(this.value)
      } else {
        this.value.forEach(item => {
          this.choosedOptions.push(this.deptMap[item.id])
          this.choosedValue = this.value
        })
      }
    },
    getNodeData(resolve) {
      this.loading = true
      getDwxxOfTree().then(dwxxResult => {
        // dwxxResult.data :
        // [{
        //   id  : "123456"
        //   name : "xx集团"
        //   pid : "000000"
        // }]
        this.loading = false
        if (dwxxResult.data) {
          this.options = dwxxResult.data
          const rootDept = []
          this.deptMap = {}
          for (let deptInfo of dwxxResult.data) {
            this.deptMap[deptInfo.id] = deptInfo
          }
          for (let deptInfo of dwxxResult.data) {
            if (!this.deptMap[deptInfo.pid]) {
              rootDept.push(deptInfo)
            }
          }
          if (resolve) {
            resolve(rootDept)
          }
        } else {
          if (resolve) {
            resolve([])
          }
        }
        this.init()
        this.createTree(dwxxResult.data)
      })
    },
    createNodeChildren(node) {
      let children = []
      for (let deptId in this.deptMap) {
        let tmpNode = this.deptMap[deptId]
        if (tmpNode.pid === node.id) {
          children.push(this.createNodeChildren(tmpNode))
        }
      }
      node.children = children
      return node
    },
    createTree() {
      this.treeData = []
      for (let deptId in this.deptMap) {
        let node = this.deptMap[deptId]
        if (!this.deptMap[node.pid]) {
          this.treeData.push(this.createNodeChildren(node))
        }
      }
    },
    loadNode(node, resolve) {
      if (node.level === 0) {
        this.getNodeData(resolve)
      } else {
        const children = []
        for (let deptId in this.deptMap) {
          if (this.deptMap[deptId].pid === node.data.id) {
            children.push(this.deptMap[deptId])
          }
          resolve(children)
        }
      }
    },
    handleCheck(data, currentData) {
      this.choosedOptions = this.multiple ? [data] : currentData.checkedNodes // this.$refs.treeRef.getCheckedNodes(false, false)
      if (this.choosedOptions.length > 0) {
        const tempMap = {}
        this.choosedOptions.forEach(op => {
          tempMap[op.id] = op
        })
        let tmpOps = []
        this.choosedOptions.forEach(op => {
          if (!tempMap[op.pid]) {
            tmpOps.push(op)
          }
        })
        this.choosedOptions = tmpOps
        this.choosedValue = this.choosedOptions.map(item => item.id)
      } else {
        this.choosedValue = []
      }
      this.$emit('input', this.multiple ? this.choosedValue : this.choosedValue[0])
    },
    chooseNode(data) {
      this.choosedOptions = [data]
      this.choosedValue = [data.id]
      this.$emit('input', data.id)
      this.$refs.selectRef.visible = false
    }
  }
}
</script>

<style scoped lang="scss">
.optionClass {
  display: none;
}

.treeClass {
  background: transparent;
  margin: 10px;
}
</style>
相关推荐
会发光的猪。2 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客2 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
周全全3 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php
ZwaterZ3 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
码农六六3 小时前
vue3封装Element Plus table表格组件
javascript·vue.js·elementui
徐同保3 小时前
el-table 多选改成单选
javascript·vue.js·elementui
快乐小土豆~~3 小时前
el-input绑定点击回车事件意外触发页面刷新
javascript·vue.js·elementui
周三有雨3 小时前
【面试题系列Vue07】Vuex是什么?使用Vuex的好处有哪些?
前端·vue.js·面试·typescript
大霞上仙5 小时前
element ui table 每行不同状态
vue.js·ui·elementui
lv程序媛5 小时前
el-table表头前几列固定,后面几列根据接口返回的值不同展示不同
javascript·vue.js·elementui