Vue2树形下拉列表选择组件封装,支持异步加载

使用vue2封装树形结构的组件,用于下拉选择,结构如下:

父组件---->封装的树形组件----->回显input组件 & tree组件

封装的树形结构组件代码如下:

<template>
  <div>
    <div @click="openTree">
      <el-input v-model="deptName" placeholder="请选择部门" @keyup.enter.native="handleQuery">
        <i slot="suffix" class="el-input__icon " :class="showTree?'el-icon-caret-bottom':'el-icon-caret-left'"
           style="position: relative;">
          <div @click.stop="changeTreeShow" style="width: 100%;height: 100%;position: absolute;top: 0;z-index: 9999"></div>
        </i>
      </el-input>
    </div>
    <div style="" class="myScrollbar treeBox" v-show="showTree">
      <dept-tree ref="deptTree" :default-dept-id="defaultDeptId" :refresh="showTree" @node-click="nodeClick"/>
    </div>
  </div>
</template>

<script>
import DeptTree from "@/views/system/dept/components/deptTree";
import {
    
    getDept} from "@/api/system/dept";

export default {
    
    
  name: "deptSelect",
  components: {
    
    DeptTree},
  props: {
    
    
    defaultDeptId: {
    
    //默认回显的部门id
      type: String
    }
  },
  data() {
    
    
    return {
    
    
      deptName: '',//用于显示的部门名称
      showTree: false//是否显示下拉的树形组件
    }
  },
  watch: {
    
    
    defaultDeptId: {
    
    
      handler(val, oldVal) {
    
    
        if (val !== oldVal) {
    
    
          this.getDeptName(val);//监听默认部门id变化,实时查询对应的部门名称进行回显
        }
      },
      immediate: true
    }
  },
  methods: {
    
    
    changeTreeShow() {
    
    
      setTimeout(() => {
    
    
        this.$nextTick(() => {
    
    //动态切换树形组件的显示与否
          this.showTree = !this.showTree
        })
      });
    },
    handleQuery() {
    
    //实现通过部门名称进行部门找的功能
      this.$refs.deptTree.queryDeptByDeptName(this.deptName);
    },
    getDeptName(deptId) {
    
    //通过部门id查询部门名称
      if (deptId) {
    
    
      //TODO 此处异步查询接口根据实际情况需要自定义
        getDept(deptId).then(res => {
    
    
          this.deptName = res.data.deptName;
        });
      }
    },
    openTree() {
    
    
    //打开下拉的树形结构
      this.showTree = true;
    },
    nodeClick(node) {
    
    
    //用户选择了树节点后的回调
      this.showTree = false //关闭树组件
      this.deptName = node.label//设置选中的部门名称
      this.$emit('setDept', node);//回传选中的节点给父组件
    }
  }
}
</script>

<style scoped>
.treeBox {
    
    
  max-height: 300px;
  overflow: auto;
  position: absolute;
  z-index: 999;
  width: 100%;
  border-radius: 0 0 8px 8px;
  border: 1px solid #e0e3e9;
  border-top: 0;
  margin-top: -4px;
}
</style>

树形组件代码:

<template>
  <div>
    <!--  部门树-->
    <el-tree
      :data="deptTree"//显示的树形结构数据,使用懒加载的时候可以用于初始化,不需要的话可以去除
      :props="defaultProps"//树形组件配置项,根据需要进行修改
      :expand-on-click-node="false"//点击节点的时候是否展开,因为点击节点的时候业务逻辑为选中,所以此处设置为不展开
      ref="tree"
      lazy //启用懒加载机制
      node-key="id"
      :load="getDeptTree"//懒加载调用的方法
      :highlight-current="true"//高亮当前行
      @node-click="handleNodeClick"//点击节点后回调的方法
    />
  </div>
</template>

<script>
//TODO 引用的api接口均需自己重新写
import {
    
    getUserProfile} from "@/api/system/user";//获取当前登录用户信息
import {
    
    getDept, getDeptByParentId, getDeptRootTree, listDept} from "@/api/system/dept";

export default {
    
    
  name: "deptTree",
  props: {
    
    
    defaultDeptId: {
    
    //默认的部门id
      type: String
    },
    refresh: {
    
    //是否需要刷新
      type: Boolean,
      default: false
    }
  },
  watch: {
    
    
    defaultDeptId(val, oldVal) {
    
    //默认的部门id
      if (val !== oldVal) {
    
    
      //同步给选中的部门id
        this.choosedDeptId = val;
      }
    },
    refresh(val, oldVal) {
    
    
      if (val !== oldVal) {
    
    
      //获取根部门
        this.getRootDept()
      }
    }
  },
  data() {
    
    
    return {
    
    
      deptTree: [],//部门tree
      userInfo: {
    
    },//当前用户信息
      choosedDeptId: this.defaultDeptId,//选中的部门id
      defaultProps: {
    
    //部门树配置
        children: 'children',
        label: 'label'
      },
    }
  },
  methods: {
    
    
    getDeptTree(node, resolve) {
    
    //部门树懒加载调用方法
      getUserProfile().then(response => {
    
    //先获取当前登录人的信息
        this.userInfo = response.data
        if (node.level === 0) {
    
    //如果是第一次加载,即加载的是第一层的
          //首次加载,根据角色进行初始化,不同的角色看到的根节点不一样
          getDept(this.userInfo.deptId).then(response => {
    
    //根据当前登录人的部门id获取根部门,实现不同的用户只能看见本部门及其下属部门的功能
            let deptInfo = response.data
            let tmp = []
            tmp.push({
    
    label: deptInfo.deptName, id: deptInfo.deptId, leaf: false})
            resolve(tmp)//添加获取的部门数据到树上
            this.deptTree = tmp;//保存树数据
          })
        } else {
    
    
          //加载子节点
          getDeptByParentId(node.data.id).then(response => {
    
    
            let tmp = []
            response.data.forEach(deptInfo => {
    
    
              tmp.push({
    
    label: deptInfo.deptName, id: deptInfo.deptId, leaf: false})
            })
            resolve(tmp)//添加获取的部门数据到树上
          })
        }
      })

    },
    getRootDept() {
    
    
    //根据当前登录人的部门id获取根部门,实现不同的用户只能看见本部门及其下属部门的功能
      getDept(this.userInfo.deptId).then(response => {
    
    
        let deptInfo = response.data
        let tmp = []
        tmp.push({
    
    label: deptInfo.deptName, id: deptInfo.deptId, leaf: false})
        this.deptTree = tmp;
      })
    },
    queryDeptByDeptName(deptName) {
    
    
    //根据部门名称查询部门列表
      if (!deptName) {
    
    
        this.getRootDept()
      } else {
    
    
      //查询部门列表
        listDept({
    
    deptName: deptName, deptIdScope: this.userInfo.deptId}).then(response => {
    
    
          let tmp = []
          response.data.forEach(deptInfo => {
    
    
            tmp.push({
    
    label: deptInfo.deptName, id: deptInfo.deptId, leaf: false})
          })
          this.deptTree = tmp;//直接赋值,不使用懒加载的机制
        })
      }
    },
    handleNodeClick(data) {
    
    
    //点击节点后的回传点击的数据给上级组件
      this.$emit('node-click', data)
    }
  }
}
</script>

<style scoped>

</style>

封装的组件调用:

ui部分:
<dept-select :default-dept-id="deptId" placeholder="请选择归属部门" @setDept="setDept"/>

js部分:
setDept(dept) {
    
    
   this.deptId = dept.id
}


猜你喜欢

转载自blog.csdn.net/geshi201028/article/details/125197658