zoukankan      html  css  js  c++  java
  • vue2-org-tree 基于VUE的部门组织架构组件,增删节点实现

    本文所用组件传送门:vue-org-tree  

    本文基于antd (其他前端组件框架操作基本都类似的: iview,elementui,boostrap-vue...)

    当然,github上还有其他类似的组件,实现方法各有不同,显示效果也有差异,但都是很方便的组件。

    看到网上有很多相关的使用教程,github上也写得很清楚,这里恕不在重复,本文主要实现增删节点。

    场景:我们通常展示部门树的时候,简单的直接就是一个下拉框展示,为了显示明显,可能会使用一些树。
       

    图片截至:(antd vue文档)

    但是简单的树形已经很难满足变态的需求了。尽管做到tree已经很自然的显示了组织架构关系了。这个时候就需要更好看,更直接的显示方式了。

    先预览一下vue2-org-tree 组件的样式:

    显示效果非常不错了。层级关系清晰明了,而且支持节点开闭,手动配置样式等功能。

    立马上手,照着官方案例搞了一个,嗯嗯,很不错,确实是大佬们想要的。

     把玩一番,颇为得意,很轻松的解决了烦人的需求。果然天道酬勤,报应不爽啊,才懒一会儿,就被泼了凉水,因为我发现一个很让人绝望的问题。这个组件不支持扩展子节点。

    是的,它只支持你把数据传进来,然后渲染出效果。然后点两下开关,横排竖排显示,没了。。。。。。刚开始认为这个组件不够全面,是的,至少支持增删的话。但是现在的前端开发,完全组件式开发。你需要飞机,就给你飞机,但是发动机,座位,机组人员,配套设施,都需要你自己去添加,因为你无法开发出一个完全适配所有配置的组件,如果你开发出来了,首先很牛,但是这个组件的库一定非常巨大,你需要适配的各种设施都在你的库里,你需要下载半小时的库包(虽然开玩笑,但确实库比较大加载是很费时的)。所以大家都趋于开发出一个小巧轻便的组件

    失望归失望,研究一番,发现组件提供的API里面有自定义渲染方式的prop:renderContent 

    既然支持自定义渲染方式,我传入一个jsx会怎么样呢?迅速找到antd的下拉菜单组件:

     附上官方源码:

    <template>
      <a-dropdown :trigger="['click']">
        <a class="ant-dropdown-link" href="#">
          Click me <a-icon type="down" />
        </a>
        <a-menu slot="overlay">
          <a-menu-item key="0">
            <a href="http://www.alipay.com/">1st menu item</a>
          </a-menu-item>
          <a-menu-item key="1">
            <a href="http://www.taobao.com/">2nd menu item</a>
          </a-menu-item>
          <a-menu-divider />
          <a-menu-item key="3">3rd menu item</a-menu-item>
        </a-menu>
      </a-dropdown>
    </template>

    通过鼠标点击展开下拉菜单。点击子菜单可以实现不同的功能。我让每一个节点都是一个下拉菜单,不就可以了吗?把上面的代码改写成jsx形式,并写入renderContent 方法里,记得定义组件renderContent 属性哦。

     renderContent (h, data) {
          return (<span><a-dropdown trigger={['click']}>
            <a>{data.title}</a>
            <a-menu slot="overlay" onclick={(key) => this.onClick(key, data)}>
              <a-menu-item v-show={data.level !== 0} key={'add'}>添加同级部门</a-menu-item>
              <a-menu-item key={'addChild'}>添加下级部门</a-menu-item>
              <a-menu-item key={'edit'}>修改部门</a-menu-item>
              <a-menu-item key={'del'} >删除部门</a-menu-item ></a-menu ></a-dropdown ></span >)
        }

    h不解释啦,就是jsx对象。data是我的数据,title是名称。onclick就是a元素的js事件,这里传递了下拉菜单的key,并用箭头函数指向自定义的onClick函数。

     onClick (keyObj, node) {
          if (keyObj.key === 'del') {
            if (node.children && node.children.length > 0) {
              this.$message.info('当前部门存在子部门,请先删除子部门')
            } else {
              this.$http.get('/rdDept/del', { params: { id: node.value } })
                .then(res => {
                  if (res.success && res.data) {
                    this.$message.success('删除成功')
                    this.loadTree()
                  } else {
                    this.$message.error(res.errorMessage)
                  }
                })
            }
          } else {
            this.$refs.modifyDept.showModal(keyObj.key, node)
          }
        }

    onclick里只处理了删除操作,并且存在子节点,就不进行删除。

    先看下目前的效果:

    视图完全没问题。操作下拉菜单:

     

    正确响应。

    写到这里,已经实现删除操作了。新增,修改操作其实已经呼之欲出了,定义一个输入框弹出层,这里就不贴具体代码了。

    显示效果如下:

     现在我们回到onClick方法的最后一行代码:

      this.$refs.modifyDept.showModal(keyObj.key, node)

    modifyDept是我新建的组件,showModal是组件的方法,key就是组件的下拉菜单key,node就是当前节点。我们来看下showModal方法:

     showModal (key, data) {switch (key) {
              case 'edit':
                this.setDept(data.title, data.value, data.parentId, data.level, `修改[${data.title}]`, data.identity)
                break
              case 'add':
                this.setDept('', -1, data.parentId, data.level, `添加同级部门[${data.title}]`, data.identity)
                break
              case 'addChild':
                data.identity = data.identity === '' ? data.value : `${data.identity}:${data.value}`
                this.setDept('', -1, data.value, data.level + 1, `添加下级部门[${data.title}]`, data.identity)
                break
              default:
                this.setDept('', -1, -1, 0, '添加研发部门', '')
                break
            }
        },
        setDept (name, id, parentId, level, title, identity) {
          this.form.setFieldsValue({ deptName: name })
          this.params.id = id
          this.params.parentId = parentId
          this.params.level = level
          this.params.thisIdentity = identity
          this.title = title
        }

    根据传递过来的key确定操作,setDept方法设置当前操作的部门的树形。

    this.params对象是传递到后台的对象。就是你想操作的对象。

    this.form.setFieldsValue({ deptName: name }) 该方法来自antd form表单api,设置输入框deptName 的值。
    输入框代码如下:
    <a-form :form="form">
      <a-form-item :label-col="{ span: 0 }" :wrapper-col="{ span: 24 }">
        <a-input v-decorator="['deptName',{rules: [{ required: true, message: '请输入研发部门' }]}]" />
      </a-form-item>
    </a-form>

    接下来,你只需要写一个form的提交操作。把params对象传递了后台,然后由后台进行更新插入操作。然后刷新你的部门树,就实现增删功能了。

    关键操作其实还是在jsx那段代码。你可以用jsx 做到你想要的任何效果。

    The end!

  • 相关阅读:
    cogs 896. 圈奶牛
    bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘
    bzoj 1007: [HNOI2008]水平可见直线
    bzoj 3673: 可持久化并查集 by zky
    bzoj 3545: [ONTAK2010]Peaks
    bzoj 1901: Zju2112 Dynamic Rankings
    动态 K th
    poj 2104 K-th Number
    bzoj 3657 斐波那契数列(fib.cpp/pas/c/in/out)
    青蛙的约会
  • 原文地址:https://www.cnblogs.com/BlueToWhite/p/11431453.html
Copyright © 2011-2022 走看看