element-ui的多级选择器cascader二次封装

E和弦的根音 · 2021-02-19 · 2303 次浏览

element-ui的多级选择器cascader维护的是一个数组, 但在实际需求中我们往往只要维护某个子项的id即可, 如部门、组织等. 在提交表单时我们把子项id post给后台, 在表单回显时需要根据子项id找到该子项的所有上级进行回显。 这时cascader将无法胜任我们的需求,

解决办法: 在cascader的基础上二次封装一个公共组件

SelectTree.vue (代码仅供参考)

<template>
  <el-cascader
    style="width:100%"
    :options="options"
    v-model="valueArr"
    @change="change"
    :props="treeProps"
    :clearable="clearable"
  ></el-cascader>
</template>

<script>
import { myDeptTree } from '@/api/userInfo'

export default {
  name: '',
  props: {
    value: {},
    // 是否多选
    multiple: {
      type: Boolean,
      default: () => false,
    },
    // 是否可选任意一级
    checkStrictly: {
      type: Boolean,
      default: () => false,
    },
    // 是否可清除
    clearable: {
      type: Boolean,
      default: () => true,
    },
    // 类型
    type: {
      type: String,
      default: () => '',
    },
  },
  components: {},

  data() {
    return {
      valueArr: [],
      options: [],
      treeProps: {
        multiple: this.multiple,
        checkStrictly: this.checkStrictly,
        value: 'id',
        label: 'categoryName',
        children: 'children',
      },
    }
  },
  watch: {
    value: {
      handler() {
        this.initData()
      },
      deep: true,
    },
  },
  methods: {
    initData() {
      if (!this.valueArr.length) {
        let val = this.getTreeDeepArr(this.value, this.options)
        this.valueArr = val
      }
      if (!this.value) {
        this.valueArr = []
      }
    },
    change(val) {
      this.$emit('input', val[val.length - 1])
    },
    getTreeDeepArr(key, treeData) {
      let childrenKey = 'children'
      if (this.type === 'organization') {
        childrenKey = 'childDeptList'
      }
      let arr = [] // 在递归时操作的数组
      let returnArr = [] // 存放结果的数组
      let depth = 0 // 定义全局层级
      // 定义递归函数
      function childrenEach(childrenData, depthN) {
        for (var j = 0; j < childrenData.length; j++) {
          depth = depthN // 将执行的层级赋值 到 全局层级

          arr[depthN] = childrenData[j].id

          if (childrenData[j].id == key) {
            // returnArr = arr; // 原写法不行, 因 此赋值存在指针关系
            returnArr = arr.slice(0, depthN + 1) //将目前匹配的数组,截断并保存到结果数组,
            break
          } else {
            if (childrenData[j][childrenKey]) {
              depth++
              childrenEach(childrenData[j][childrenKey], depth)
            }
          }
        }
        return returnArr
      }
      return childrenEach(treeData, depth)
    },
    initOptions() {
      switch (this.type) {
        case 'organization':
          this.organization()
          break

        default:
          break
      }
    },
    async organization() {
      let res = await myDeptTree()
      this.treeProps.label = 'deptName'
      this.treeProps.children = 'childDeptList'
      this.options = res
      this.initData()
    },
  },
  mounted() {
    this.initOptions()
  },
}
</script>

页面中使用

<SelectTree v-model="searchData.deptId" type="organization" checkStrictly />
如果有错误或者不严谨的地方,请务必给予指正,十分感谢。如果喜欢或者有所启发,欢迎评论,对作者也是一种鼓励。
查看评论 - 0 条评论