1. 程式人生 > 程式設計 >Vue使用el-tree 懶載入進行增刪改查功能的實現

Vue使用el-tree 懶載入進行增刪改查功能的實現

關於的樹形展示 使用到專案:以樹的形式非同步展現
效果圖先放:

樹形結構展示圖

找到element-ui的官方文件,el-tree。(地址:https://element.eleme.cn/#/zh-CN/component/tree )

專案需求:以懶載入的形式展示,目錄根據需求需要有新增 編輯 刪除 操作以及操作後的重新整理樹結構

那我們現在開始吧

一、

在這裡插入圖片描述

懶載入:Tree的懶載入,用一個屬性控制:lazy。使用lazy,就要使用load來載入資料進行渲染樹
原理:初始化觸發load函式先載入初始資料,通過點選某個節點,觸發load函式,來載入這個節點下的子節點。
優點:適合資料量比較大的時候,對部分節點重新整理也比較友好

二、

在這裡插入圖片描述

自定義節點:節點後新增操作按鈕

在這裡插入圖片描述
在這裡插入圖片描述

簡單例子官網上就有示例

**

主要講講更新節點

**
當對節點進行編輯、刪除時,需要更新樹,只需更新節點,不必更新全部的樹即可。
原理:更新節點,其實更新的是該節點的子節點,不包括本節點。刪除該節點的子節點,重新請求資料獲取本節點的子節點資料進行重新渲染。

// refreshNode:要重新整理的節點;newNodeData:新的子節點資料
refreshNode.splice(0,refreshNode.length);
refreshNode.doCreateChildren(newNodeData);

理解一下:
1>.方法node-click

呼叫函式menuNodeClick,記錄點選的節點資訊,對節點操作前,必然先點選選中某個節點。此函式監聽點選節點事件,只要點選了節點,就觸發:

menuNodeClick(data,node,treeNode) {
    this.selectNodeData = data
    this.selectNode = node
}

2>.節點操作後重新整理節點即可,通過不同場景可以選擇重新整理本節點(node)還是重新整理本節點的父節點(node.parent):

/**
* 重新整理節點資料
* @node [node/Object]: 重新整理的節點node,重新整理node以下的所有節點
* @type [String]: node的型別,'node'表示node是樹的節點資訊Node;'data'表示node是樹節點資訊中的data資料
*/
refreshTreeNode(node,type) {
    let refreshNode;
    // 拿到要更新節點的子節點
    if(type === 'node') {
        refreshNode = node.childNodes
    }else if(type === 'data') {
        let getNode = this.$refs.tree.getNode(node)
        refreshNode = getNode.childNodes
    }
    // 刪除原有的子節點
    refreshNode.splice(0,refreshNode.length);
    //重新請求資料,更新節點
    this.requestTreeNode(node)
}

3.選擇框checkBox:

如果懶載入中,有選擇框,需要將有選擇框的資料加載出來,然後通過屬性default-checked-keys來勾選,通過default-expanded-keys設定展開的節點。

4.單選:
如果在懶載入中,有單選項,則設定選中即可:

// 設定當前節點選中
this.$refs.tree.setCurrentKey(
    this.selectNodeData[this.nodeKey]
)

不管是單選還是多選,在第一次載入時,後臺要給的,不只是選中資訊,還需要選中節點所在分支的所有節點資訊,賦值給default-expanded-keys以便可使節點所在分支從上到選擇項都展開。但往往,後臺可能給的,只是選中值的資訊,這就要前端自己封裝資料,獲取需要展開的分支資訊。根據資料格式不同,用不同的方法
1)樹形單層資料格式:

[
{...},
{...},
{...}
]

這種格式的資料,【點選一層,載入一層】、【點選一層,載入該點選層的多層子節點】兩種情況都可以滿足。第一種不需要進行資料處理;第二種情況,需要在每條資料中注入一個欄位,用來關聯父子節點,然後將資料封裝處理成el-tree所需要的格式,用一個遞迴函式整合資料(假設關聯欄位為parentId,nodeKey為id,樹的子節點欄位為children,需要載入id為'N'的多層子節點)(注:遞迴函式會影響效能,謹慎使用)

2).多層資料(假設子節點的屬性名是children)

[
    {
        ...,children: [
            {
                ...,children: [
                    {
                        ...,children: [...],},{
                        ...,}
                ]
            },{
                ...,}
                ]
            }
        ]
    }
    
]

這種格式的資料,單層、多層都可以滿足,不需要做處理。
選中值整合並展開選中值所在的樹:多層資料可由後臺給出選中節點所在的整個分支的值,賦給default-expanded-keys進行展開。也可以自己做篩選,寫一個遞迴函式,將多層資料迴圈,找到選中值的節點的分支來設定展開(假設nodeKey為id,樹的子節點欄位為children,需要展開id為'N'的節點所在的整個分支)

懶載入示例:
HTML控制元件:

<el-tree
            :data="treeData"
            :props="defaultProps"
            :load="loadNodeTree"
            @node-click="handleNodeClick"
            lazy
            :expand-on-click-node="false"
             :default-expanded-keys="['1']"
            node-key="id"
            :highlight-current="true"
          >
            <span class="custom-tree-node" slot-scope="{ node,data }">
              <span class="treeLeft">{{ node.label }}</span>
              <span class="treeRight">
                <i
                  v-if="node.level === 1"
                  @click="() => appendNode(node,data)"
                  class="el-icon-plus"
                  style="color: blue"
                ></i>
                <!--增加分組-->
                <!-- 根節點不需要刪除和重新命名 -->

                <i
                  v-if="data.id !== 0"
                  @click="() => deleteNode(node,data)"
                  class="el-icon-delete"
                  style="color: red"
                ></i>
                <!--刪除分組-->

                <i
                  v-if="data.id !== 0"
                  @click="() => editNode(node,data)"
                  class="el-icon-edit"
                  style="color: blue"
                ></i>
                <!--重新命名分組-->
              </span>
            </span>
          </el-tree>

vue:
data裡面定義變數

 // 樹形選單
      treeData: [],// 樹節點
      defaultProps: { // 修改el-tree預設dawww.cppcns.comta陣列引數
        children: 'children',label: 'name',id: 'id',parentId: 'parentId',isLeaf: 'leaf' // 指定節點是否為葉子節點,僅在指定了 lazy 屬性的情況下生效
      },

methods:
載入樹形選單部分

 // 載入 樹資料
    loadNodeTree(node,resolve) {
      const that = this
      if (node.level === 0) {
        that.loadtreeData(node,resolve)
      } else if (node.level === 1) {
        that.getChildByList(node,resolve)
      }
    },// 獲取loadtreeData 就是父節點資料,getChildByList就是非同步獲取子節點資料
    loadtreeData(nodeData,resolve) {
      const dataType = {
        pageIndex: 1,pageSize: 100000
      }
      getAlltype(dataType)
        .then(res => {
          const rootChildren = []
          if (res.code === 200) {
            const data = res.data.list
            data.map(item => {
              rootChildren.push({
                name: item.typeName,parentId: '',id: item.id,leaf: false,children: []
              })
            })
            //如果resolve有內容就是懶載入走查詢 否則走的是修改
            if (resolve) {
              resolve(rootChildren)
            } else {
              nodeData.childNodes = []
              nodeData.doCreateChildren(rootChildren)
            }
          } else {
            resolve([])
          }
        })
    },// 獲取子節點請求
    getChildByList(nodeData,resolve) {
      var _parentID = nodeData.data.id
      const typeSpec = {
        typeId: _parentID,pageIndex: 1,pageSize: 100000
      }
      getAlltypeSpec(typeSpec).then(res => {
        const rootChildren = []
        if (res.code === 200) {
          const data = res.data.list
          data.map(item => {
            rootChildren.push({
              name: item.description,parentId: item.typeId,leaf: truehttp://www.cppcns.com,children: []
            })
          })
          if (resolve) {
            resolve(rootChildren)
          } else {
            nodeData.childNodes = []
            nodeData.doCreateChildren(rootChildren)
          }
        } else {
          return false
        }
      }).catch(err => {
        console.log(err)
      })
    },// 節點點選事件
    handleNodeClick(data,node) {
      this.addnode = node
      this.adddata = data
      if (node.level === 1) {
        this.queryForm.typeId = node.data.id
        this.queryForm.typeSpecId = ''
      } else if (node.level === 2) {
        this.queryForm.typeId = node.data.parentId
        this.queryForm.typeSpecId = node.data.id
      }
      this.query()
    },

節點操作:增加節點 修改節點 刪除節點 (操作自己節點要傳父節點資訊才能找到自己當前節點,操作子節點就傳當前節點 結論:父節點操作子節點)

 // 樹節點增加 型別規格
    appendNode(node,data) {
      this.addTypesSpec = {
        typeName: node.data.name,typeId: node.data.id
      }
      this.createTypesSpecDialog = true
    },// 樹型別修改
    editNode(node,data) {
      const typeId = node.data.parentId
      // 一級 型別
      if (node.level === 1) {
        this.editTypesDialog = true
        this.editTypes = {
          id: node.data.id,typeName: node.data.name
        }
      } else {
        this.editTypesSpecDialog = true
        this.getSelectTypes()
        // this.editTypesSpec = Object.assign({},node.data)
        this.editTypesSpec = {
          typeId: typeId,id: node.data.id,description: node.data.name
        }
      }
    },// 樹型別刪除
    deleteNode(node,data) {
      // 一級 型別
      if (node.level === 1) {
        this.$msgbox.confirm('此操作將刪除資產型別資料,是否繼續?','刪除提示',{
          confirmButtonText: '確定',cancelButtonText: '取消',type: 'warning'
        }).then(() => {
          typeDel(node.data.id).then(
            resp => {
              this.$message('刪除成功')
              this.query()
              this.loadNodeTree(node.parent)
            },err => {
              console.log('err',err)
            }
          )
        }).catch(() => {
          this.$message.error('已取消')
        })
      } else {
        this.$msgbox.confirm('此操作將刪除資產型別規格資料,http://www.cppcns.com         type: 'warning'
        }).then(() => {
          typeSpecDel(node.data.id).then(
            resp => {
              this.loadNodeTree(node.parent)
              this.$message('刪除成功')
              this.query()
            },err)
            }
          )
        }).catch(() => {
          this.$message.error('已取消')
        })
      }
    },

節點觸發之後顯示彈框 走正常的彈框增加修改刪除操作,只不過在提交後臺請求返回操作成功之後需要再一次載入樹形結構 所以在這裡再一次呼叫載入樹形方法,傳的node 當觸發點選樹形的時候可以儲存一下,我的是handleNodeClick這個方法 不管點選修改 增加還是刪除都儲存下點選的node

 this.$message('編輯成功')
              this.loadNodeTree(this.addnode.parent)

1.設定展開和收縮

if (!node.expanded) {
    node.expand();
}else {
    node.collapse();
}

2.獲取父節點

node.parent

看得懂的就看吧 程式碼可以優化 但是最近沒啥時間 看不懂的能清楚這個邏輯也行啊 下次見

到此這篇關於Vue使用el-tree 懶載入進行增刪改查的文章就介紹到這了,更多相關Vue el-tree 懶載入內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!