我看有不少人看到这个《Ant-design-vue 树形控件tree 新增节点,删除节点,编辑节点的解决方案》文章以后,有不少疑惑,关于删除,增加的问题,以及key重复的问题,我发的这篇文章只是提供了一个思路。

整合下,还是对你们详解一下,可能有些人看得不是很明白

关于dom

<a-button type="primary" @click="add">添加顶级菜单</a-button>
      <a-tree
        showLine
        @expand="onExpand"
        :expandedKeys="expandedKeys"
        :autoExpandParent="autoExpandParent"
        :treeData="treeData"
        style="margin-top:20px"
      >
        <template slot="custom" slot-scope="item">
          <span>{{ item.title }}</span>
          <a-button size="small" class="but_type" style="right:220px;" @click="()=> stop(item)">{{ item.menuStatus===0?'启用':'禁用' }}</a-button>
          <a-button size="small" class="but_type" style="right:160px;" @click="()=> append(item)">新增</a-button>
          <a-button
            class="but_type"
            size="small"
            style="right:100px;"
            @click="()=> handleEdit(item)"
          >编辑</a-button>
          <a-button class="but_type" size="small" @click="(e)=> remove(item)">删除</a-button>
        </template>
      </a-tree>

在DOM中,关于树的操作一共有4个事件,分别是

  • 添加顶级菜单事件add,
  • 启用和禁用菜单事件stop,
  • 新增菜单事件append,
  • 删除菜单事件remove
  • 编辑菜单事件handleEdit

关于逻辑

  • 首先我这边后台给的是一个一维数组,我需要把后台给的数组转换为树形结构,因此写了个方法
function treeDataTranslate (data, id = 'pid', pid = 'parentId') {
  var res = []
  var temp = {}
  for (var i = 0; i < data.length; i++) {
    data[i]['key'] = data[i].pid
    data[i]['title'] = data[i].menuName
    temp[data[i][id]] = data[i]
    data[i].scopedSlots = { title: 'custom' }
  }
  for (var k = 0; k < data.length; k++) {
    if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) {
      if (!temp[data[k][pid]]['children']) {
        temp[data[k][pid]]['children'] = []
      }
      if (!temp[data[k][pid]]['_level']) {
        temp[data[k][pid]]['_level'] = 1
      }
      data[k]['_level'] = temp[data[k][pid]]._level + 1

      temp[data[k][pid]]['children'].push(data[k])
    } else {
      res.push(data[k])
    }
  }
  return res
}

通过这个方法转换出来的数据就是我想要的数据结构即DOM中的treeData数据

  • 其次当我需要修改和删除菜单的时候我需要在treeData中找到我需要删除和修改的项,因此也需要写一个工具函数
//该函数接收4个参数,option为我需要修改或者删除的数据项,arr为格式化后的treeData,type是需要操作的类型,默认为delect,obj为编辑后的数据,默认为空对象
searchOption (option, arr, type = 'delect', obj = {}) {
//首先循环arr最外层数据
      for (let s = 0; s < arr.length; s++) {
      //如果匹配到了arr最外层中的我需要修改的数据
        if (arr[s].key === option.key) {
        //判断需要操作的类型
          if (type === 'delect') {
          	//删除即删除即可
            arr.splice(s, 1)
          } else {
            //如果是修改,利用Object.assign()组合符合arr数据格式的对象,并进行修改
            this.$set(
              arr,
              s,
              Object.assign(obj, {
                key: obj.pid,
                title: obj.menuName,
                children: option.children,
                scopedSlots: { title: 'custom' }
              })
            )
          }
          break
        } else if (arr[s].children && arr[s].children.length > 0) {
          // 递归条件
          this.searchOption(option, arr[s].children, type, obj)
        } else {
          continue
        }
      }
    },
  • 关于增加菜单就不用说了,找到父级id,将增加的数据传给后台,成功后重新获取tree数据就行
  • 编辑菜单
handleEdit(data){
   //data为原数据,this.addParamData为修改后的数据
	//this.addParamData为传给后台接口的参数,具体依据项目而定
	saveSysMenu(this.addParamData)
          .then(result => {
            if (result) {
              this.scopeVisible = false
              this.noticeMessage('操作成功')
              //编辑成功以后后台会把编辑成功后的菜单数据返回回来,然后调用this.searchOption()方法即可
              this.scopeTitle === '编辑菜单'
                ? this.searchOption(this.addData, this.treeData, 'edit', result.result)
                : this.getMenuList()
            }
          })
          .catch(err => {
            console.log(err)
          })
}

  • 删除菜单
remove(data){
	deleteMenu({ pid: data.pid })
        .then(result => {
          if (result) {
            this.visible = false
            //删除成功后调用this.searchOption()的删除方法即可
            this.searchOption(this.addData, this.treeData)
          }
        })
        .catch(err => {
          console.log(err)
        })
        .finally(() => {
          this.confirmLoading = false
        })
}

此案例只是提供一种思路,主要是借鉴为主

Logo

前往低代码交流专区

更多推荐