關於《Ant-design-vue 樹形控件tree 新增節點,刪除節點,編輯節點的解決方案》文章的補充

我看有不少人看到這個《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
        })
}

此案例只是提供一種思路,主要是借鑑爲主

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章