element-ui的Tree樹組件使用技巧

1,前言


最近這段時(shí)間在做一個(gè)新的模塊钢拧,其中有一個(gè)三層的樹結(jié)構(gòu),產(chǎn)品經(jīng)理提出了一個(gè)很古怪的需求炕横,整的我只能自己控制樹的交互源内,寫完之后,感覺對(duì)這個(gè)組件的用法有了不一樣的了解份殿,故而寫下來膜钓。

2,需求


  • 如果上級(jí)節(jié)點(diǎn)勾選了卿嘲,則底下所有節(jié)點(diǎn)也勾選
  • 如果是一個(gè)個(gè)勾選子級(jí)節(jié)點(diǎn)颂斜,直至勾選滿所有子級(jí),則該父級(jí)節(jié)點(diǎn)不能勾選拾枣,只能算選中狀態(tài)
  • 已勾選的節(jié)點(diǎn)不能展開沃疮,如果是展開了再勾選的盒让,要自動(dòng)收縮回去

遇見問題:

問題1:后端數(shù)據(jù)不友好,無唯一key值(有重復(fù)key)司蔬,導(dǎo)致Tree組件無唯一的key

問題2:后端數(shù)據(jù)不友好邑茄,第一層第二層的字段和第三層的字段不一致(第一層字段是dept_id,子集字段是children俊啼,第二層子集字段是porjs肺缕,第三層字段又是porj_id

問題3:不能使用check-strictly,也就是Tree組件自帶的父子關(guān)聯(lián)吨些,只能手動(dòng)控制checkbox的選中狀態(tài)

問題4:提交給后端的數(shù)據(jù)搓谆,如果一級(jí)二級(jí)節(jié)點(diǎn)被勾選炒辉,則不用傳遞其下層結(jié)構(gòu)豪墅,如果不是被勾選,則需要傳遞其下層結(jié)構(gòu)

如圖:


QQ截圖20210924101557.png

不過還好這個(gè)樹結(jié)構(gòu)只有三層黔寇,辦法還是有的偶器。(如果是未知層級(jí)就難了)

3,解決思路


問題1:無唯一key

這個(gè)好辦缝裤,接口請(qǐng)求到數(shù)據(jù)之后屏轰,深拷貝一份,遍歷一下憋飞,給id手動(dòng)添加字符來使它們變成唯一的霎苗,最后提交的時(shí)候去掉前面添加的字符

// 將所有id根據(jù)層級(jí)加上壹,貳榛做,叁
handlePushLabel(data) {
  try {
    data.forEach(item1 => {
      item1.dept_id += '壹'
      if (item1.children && item1.children.length > 0) {
        item1.children.forEach(item2 => {
          item2.dept_id += '貳'
          item2.parent_id += '壹'
          if (item2.children.length > 0) {
            item2.children.forEach(item3 => {
              item3.dept_id += '叁'
              item3.parent_id += '貳'
            })
          }
        })
      }
    })
    return data
  } catch (error) {
    console.warn(error)
  }
}
// 將數(shù)據(jù)的key恢復(fù)為原來的
treeList.forEach(item1 => {
  item1.dept_id = item1.dept_id.replace('壹', '')
  if (item1.children.length > 0) {
    item1.children.forEach(item2 => {
      item2.dept_id = item2.dept_id.replace('貳', '')
      item2.parent_id = item2.parent_id.replace('壹', '')
      if (item2.children.length > 0) {
        item2.children.forEach(item3 => {
          item3.dept_id = item3.dept_id.replace('叁', '')
          item3.parent_id = item3.parent_id.replace('貳', '')
        })
      }
    })
  }
})

問題2:第一層第二層的字段和第三層的字段不一致

這個(gè)也好辦唁盏,最好的辦法是后端調(diào)整成一樣的,但是如果碰見博主這樣的無法溝通的后端检眯,只能前端自己轉(zhuǎn)換字段了厘擂,這里采用的是forEach遍歷,然后使用map替換對(duì)象鍵名锰瘸。

// 將樹數(shù)據(jù)的projs字段和proj_id和proj_name改名
handleChangeKey(data) {
  try {
    const tree = data
    tree.forEach(item => {
      if (item.children) {
        const arr = item.children
        // 將projs字段轉(zhuǎn)為children
        item.children = arr.map(item1 => {
          if (item1.projs.length > 0) {
            const obj = item1.projs
            const parent_id = item1.dept_id
            // 將proj_id字段轉(zhuǎn)為dept_id 將proj_name字段轉(zhuǎn)為dept_name
            // 并添加depth深度和父節(jié)點(diǎn)id
            item1.projs = obj.map(item2 => {
              return {
                dept_id: item2.proj_id,
                dept_name: item2.proj_name,
                depth: 3,
                parent_id
              }
            })
          }
          return {
            dept_id: item1.dept_id,
            dept_name: item1.dept_name,
            depth: item1.depth,
            parent_id: item1.parent_id,
            children: item1.projs
          }
        })
      }
    })
    return this.handlePushLabel(tree)
  } catch (error) {
    console.warn(error)
  }
}

問題3:不能使用check-strictly

這個(gè)就比較繁瑣了刽严,不能使用Tree自帶的勾選父子關(guān)聯(lián)(原因看需求2),只能自己手寫一二三級(jí)節(jié)點(diǎn)的勾選邏輯避凝。這樣的話舞萄,二級(jí)和三級(jí)節(jié)點(diǎn)需要有個(gè)parent_id字段,也就是其父級(jí)的id管削,且有一個(gè)depth字段鹏氧,代表其深度1,2佩谣,3把还。

<el-tree
  @check-change="handleTreeClick"
  :data="treeList"
  show-checkbox
  :default-expand-all="false"
  :check-strictly="true"
  @node-expand="handleTreeOpen"
  node-key="dept_id"
  ref="tree"
  highlight-current
  :props="defaultProps"
/>

Tree組件加上ref屬性,設(shè)置check-strictlytrue,利用@check-change監(jiān)聽節(jié)點(diǎn)勾選吊履,利用@node-expand監(jiān)聽節(jié)點(diǎn)展開收起安皱,設(shè)置node-key為每個(gè)節(jié)點(diǎn)的id

思路是:通過@check-change的回調(diào)艇炎,拿到第一個(gè)參數(shù)data酌伊,這個(gè)data里包含該節(jié)點(diǎn)的數(shù)據(jù),通過這個(gè)數(shù)據(jù)可以拿到depth判斷他是第幾層節(jié)點(diǎn)缀踪,還可以拿到parent_id找到它的上級(jí)節(jié)點(diǎn)居砖。根據(jù)這個(gè)區(qū)分一二三級(jí)節(jié)點(diǎn),然后通過獲取到的id驴娃,使用this.$refs.tree.getNode(id)可以獲取到節(jié)點(diǎn)Node奏候。設(shè)置節(jié)點(diǎn)Nodecheckedtrue,則該節(jié)點(diǎn)會(huì)變成勾選狀態(tài)唇敞。設(shè)置它的indeterminatetrue蔗草,則會(huì)變成選中狀態(tài),設(shè)置expandedtrue疆柔,則是展開狀態(tài)咒精。也可以通過this.$refs.tree.setChecked(id, true)來設(shè)置選中。

問題4:提交給后端的數(shù)據(jù)

這個(gè)就是坑了旷档,需要先把之前改變的key變回去模叙,還有子級(jí)的鍵名改回去,然后根據(jù)是勾選還是只是單純的選中來拼接數(shù)據(jù)鞋屈。在這里用到了getCheckedNodes來獲取目前被選中的節(jié)點(diǎn)所組成的數(shù)組范咨,也用到了getHalfCheckedNodes獲取半選中的節(jié)點(diǎn)所組成的數(shù)組。

4谐区,完整代碼


export default {
  // 將樹數(shù)據(jù)的projs字段和proj_id和proj_name改名
  handleChangeKey(data) {
    try {
      const tree = data
      tree.forEach(item => {
        if (item.children) {
          const arr = item.children
          // 將projs字段轉(zhuǎn)為children
          item.children = arr.map(item1 => {
            if (item1.projs.length > 0) {
              const obj = item1.projs
              const parent_id = item1.dept_id
              // 將proj_id字段轉(zhuǎn)為dept_id 將proj_name字段轉(zhuǎn)為dept_name
              // 并添加depth深度和父節(jié)點(diǎn)id
              item1.projs = obj.map(item2 => {
                return {
                  dept_id: item2.proj_id,
                  dept_name: item2.proj_name,
                  depth: 3,
                  parent_id
                }
              })
            }
            return {
              dept_id: item1.dept_id,
              dept_name: item1.dept_name,
              depth: item1.depth,
              parent_id: item1.parent_id,
              children: item1.projs
            }
          })
        }
      })
      return this.handlePushLabel(tree)
    } catch (error) {
      console.warn(error)
    }
  },
  // 將所有id根據(jù)層級(jí)加上壹湖蜕,貳,叁
  handlePushLabel(data) {
    try {
      data.forEach(item1 => {
        item1.dept_id += '壹'
        if (item1.children && item1.children.length > 0) {
          item1.children.forEach(item2 => {
            item2.dept_id += '貳'
            item2.parent_id += '壹'
            if (item2.children.length > 0) {
              item2.children.forEach(item3 => {
                item3.dept_id += '叁'
                item3.parent_id += '貳'
              })
            }
          })
        }
      })
      return data
    } catch (error) {
      console.warn(error)
    }
  },
  /**
  * 樹的選中狀態(tài)發(fā)生變化時(shí)
  * @param {Object} data 該節(jié)點(diǎn)的數(shù)據(jù)
  * @param {Object} on 節(jié)點(diǎn)本身是否被選中
  * @param {Object} child 節(jié)點(diǎn)的子樹中是否有被選中的節(jié)點(diǎn)
  */
  handleTreeClick(data, on, child) {
    try {
      this.form.tree = data
      if (data.depth === 1) {
        this.handleOneNode(on, data)
      } else if (data.depth === 2) {
        this.handleTwoNode(on, data)
      } else if (data.depth === 3) {
        this.handleThreeNode(on, data)
      }
    } catch (error) {
      console.warn(error)
    }
  },
  /**
  * 一級(jí)節(jié)點(diǎn)處理
  * @param {Boolean} on 是否被選中
  * @param {Object} data 當(dāng)前節(jié)點(diǎn)的數(shù)據(jù)
  */
  handleOneNode(on, data) {
    try {
      const tree = this.$refs.tree
      // 如果當(dāng)前節(jié)點(diǎn)未被選中且為半選狀態(tài)
      const node = tree.getNode(data.dept_id)
      if (node.indeterminate && !node.checked) return
      // 如果當(dāng)前節(jié)點(diǎn)被選中則不能展開
      if (node.checked && node.expanded) node.expanded = false
      // 勾選所有下級(jí)
      let arr = []
      if (data.children.length > 0) {
        data.children.forEach(item => {
          // 篩選出所有的下級(jí)key
          arr.push(item.dept_id)
          if (item.children.length > 0) {
            item.children.forEach(child => {
              // 篩選出所有的下下級(jí)key
              arr.push(child.dept_id)
            })
          }
        })
      }
      // 選中or取消
      if (on) {
        arr.forEach(dept => {
          tree.setChecked(dept, true)
        })
      } else {
        arr.forEach(dept => {
          tree.setChecked(dept, false)
        })
      }
    } catch (error) {
      console.warn(error)
    }
  },
  /**
  * 二級(jí)節(jié)點(diǎn)處理
  * @param {Boolean} on 是否被選中
  * @param {Object} data 當(dāng)前節(jié)點(diǎn)的數(shù)據(jù)
  */
  handleTwoNode(on, data) {
    try {
      const tree = this.$refs.tree
      const node = tree.getNode(data.dept_id)
      // 如果當(dāng)前是半選
      if (node.indeterminate && !node.checked) return
      // 如果當(dāng)前節(jié)點(diǎn)被選中則不能展開
      if (node.checked && node.expanded) node.expanded = false
      // 上級(jí)節(jié)點(diǎn)
      const parentNode = tree.getNode(data.parent_id)
      // 勾選所有下級(jí)
      let arr = []
      if (data.children.length > 0) {
        data.children.forEach(item => {
          // 篩選出所有的下級(jí)key
          arr.push(item.dept_id)
        })
      }
      // 選中or取消
      if (on) {
        arr.forEach(dept => {
          tree.setChecked(dept, true)
        })
        // 如果上級(jí)節(jié)點(diǎn)不是被勾選則讓上級(jí)節(jié)點(diǎn)半勾選
        if (!parentNode.checked) {
          parentNode.indeterminate = true
        }
      } else {
        // 先取消所有下級(jí)勾選
        arr.forEach(dept => {
          tree.setChecked(dept, false)
        })
        // 如果上級(jí)節(jié)點(diǎn)被勾選則讓上級(jí)節(jié)點(diǎn)半勾選
        if (parentNode.checked) {
          parentNode.indeterminate = true
          // 如果上級(jí)是半選宋列,則循環(huán)判斷下級(jí)是否還存在勾選的昭抒,來決定上級(jí)是否需要去掉半選
        } else if (parentNode.indeterminate) {
          const parentData = parentNode.data || []
          let bool = true
          const children = parentData.children
          const childArr = []
          // 篩選出所有兄弟節(jié)點(diǎn)的key
          if (children && children.length > 0) {
            children.forEach(childItem => {
              childArr.push(childItem.dept_id)
            })
          }
          // 循環(huán)判斷
          if (childArr.length > 0) {
            for (let i of childArr) {
              let thisNode = tree.getNode(i)
              // 如果有一個(gè)是勾選或者半選
              if (thisNode.checked || thisNode.indeterminate) {
                bool = false
              }
            }
          }
          if (bool) {
            parentNode.indeterminate = false
          }
        }
      }
    } catch (error) {
      console.warn(error)
    }
  },
  /**
  * 三級(jí)節(jié)點(diǎn)處理
  * @param {Boolean} on 是否被選中
  * @param {Object} data 當(dāng)前節(jié)點(diǎn)的數(shù)據(jù)
  */
  handleThreeNode(on, data) {
    try {
      // 1,如果勾選了炼杖,上級(jí)節(jié)點(diǎn)沒選灭返,則把上級(jí)節(jié)點(diǎn)和上上級(jí)改為半選
      // 2,如果取消了坤邪,上級(jí)節(jié)點(diǎn)如果是勾選熙含,則把上級(jí)節(jié)點(diǎn)和上上級(jí)改為半選
      const tree = this.$refs.tree
      // 上級(jí)節(jié)點(diǎn)
      console.log(data)
      const parentNode = tree.getNode(data.parent_id)
      const forefathersKey = parentNode.data.parent_id
      // 祖先節(jié)點(diǎn)
      console.log(parentNode)
      console.log(forefathersKey)
      const forefathersNode = tree.getNode(forefathersKey)
      console.log(forefathersNode)
      // 如果當(dāng)前節(jié)點(diǎn)被勾選
      if (on) {
        // 如果上級(jí)節(jié)點(diǎn)未被勾選,則讓他半選
        if (!parentNode.checked) {
          parentNode.indeterminate = true
        }
        // 如果祖先節(jié)點(diǎn)未被勾選艇纺,則讓他半選
        if (!forefathersNode.checked) {
          forefathersNode.indeterminate = true
        }
        // 如果當(dāng)前節(jié)點(diǎn)是被取消勾選
      } else {
        const parentArr = []
        const forefathersArr = []
        const parentData = parentNode.data
        const forefathersData = forefathersNode.data
        let parentBool = true
        let forefathersBool = true
        // 篩選出所有兄弟key怎静,如果有勾選的則代表上級(jí)不需要去除勾選
        if (parentData.children.length > 0) {
          parentData.children.forEach(parent => {
            parentArr.push(parent.dept_id)
          })
          for (let i of parentArr) {
            let thisNode = tree.getNode(i)
            if (thisNode.checked) {
              parentBool = false
            }
          }
        }
        // 為tree則代表沒有三級(jí)節(jié)點(diǎn)被勾選邮弹,此時(shí)上級(jí)去除勾選
        if (parentBool) {
          parentNode.checked = false
          parentNode.indeterminate = false
        } else {
          parentNode.indeterminate = true
        }
        // 篩選出所有上級(jí)的兄弟key,如果有勾選的則代表上級(jí)不需要去除勾選
        if (forefathersData.children.length > 0) {
          forefathersData.children.forEach(parent => {
            forefathersArr.push(parent.dept_id)
          })
          for (let i of forefathersArr) {
            let thisNode = tree.getNode(i)
            if (thisNode.checked || thisNode.indeterminate) {
              forefathersBool = false
            }
          }
        }
        if (forefathersBool) {
          forefathersNode.indeterminate = false
        }
      }
    } catch (error) {
      console.warn(error)
    }
  },
  /**
  * 樹被展開時(shí)
  * @param {Object} data 該節(jié)點(diǎn)的數(shù)據(jù)
  * @param {Object} node 節(jié)點(diǎn)對(duì)應(yīng)的Node
  * @param {Object} ref 節(jié)點(diǎn)組件
  */
  handleTreeOpen(data, node) {
    // 如果節(jié)點(diǎn)被選中則不讓展開
    if (node.checked) {
      Tip.warn('當(dāng)前層級(jí)已被全選蚓聘,無法展開腌乡!')
      node.expanded = false
    }
  },
  // 拼接出需要的樹數(shù)據(jù)
  handleJoinTree() {
    try {
      const tree = this.$refs.tree
      const treeList = _.cloneDeep(this.treeList)
      // 被選中的節(jié)點(diǎn)
      const onItem = tree.getCheckedNodes()
      // 半選中的節(jié)點(diǎn)
      const halfItem = tree.getHalfCheckedNodes()
      const oneArr = []
      const twoArr = []
      const threeArr = []
      const oneArr_ = []
      const twoArr_ = []
      const threeArr_ = []
      // 節(jié)點(diǎn)分層
      if (onItem.length > 0) {
        onItem.forEach(item => {
          switch (item.depth) {
            case 1:
              oneArr.push(item.dept_id)
              break
            case 2:
              twoArr.push(item.dept_id)
              break
            case 3:
              threeArr.push(item.dept_id)
              break
          }
        })
      }
      if (halfItem.length > 0) {
        halfItem.forEach(item => {
          switch (item.depth) {
            case 1:
              oneArr_.push(item.dept_id)
              break
            case 2:
              twoArr_.push(item.dept_id)
              break
            case 3:
              threeArr_.push(item.dept_id)
              break
          }
        })
      }
      const oneList = this.handlejoinOne(treeList, oneArr, oneArr_)
      const twoList = this.handlejoinTwo(treeList, twoArr, twoArr_)
      const threeList = this.handlejoinThree(treeList, threeArr, threeArr_)
      // 將第二層拼進(jìn)第一層
      oneList.forEach(item => {
        twoList.forEach(item2 => {
          if (item2.parent_id === item.dept_id) {
            if (!item.isOn) {
              item.children.push(item2)
            }
          }
        })
      })
      // 將第三層拼進(jìn)第二層
      oneList.forEach(child1 => {
        if (child1.children.length > 0) {
          child1.children.forEach(child2 => {
            threeList.forEach(child3 => {
              if (child3.parent_id === child2.dept_id) {
                if (!child2.isOn) {
                  child2.children.push(child3)
                }
              }
            })
          })
        }
      })
      return oneList
    } catch (error) {
      console.warn(error)
    }
  },
  // 返回第一層
  handlejoinOne(treeList, oneArr, oneArr_) {
    try {
      // 找出第一層節(jié)點(diǎn)
      const oneList = []
      treeList.forEach(item => {
        for (let i of oneArr) {
          if (item.dept_id === i) {
            oneList.push({
              dept_id: item.dept_id,
              children: [],
              isOn: true,
              name: item.dept_name
            })
          }
        }
        for (let i of oneArr_) {
          if (item.dept_id === i) {
            oneList.push({
              dept_id: item.dept_id,
              children: [],
              isOn: false,
              name: item.dept_name
            })
          }
        }
      })
      return oneList
    } catch (error) {
      console.warn(error)
    }
  },
  // 返回第二層
  handlejoinTwo(treeList, twoArr, twoArr_) {
    try {
      const twoList = []
      treeList.forEach(item => {
        if (item.children.length > 0) {
          item.children.forEach(item2 => {
            for (let i of twoArr) {
              if (item2.dept_id === i) {
                twoList.push({
                  dept_id: item2.dept_id,
                  children: [],
                  isOn: true,
                  parent_id: item2.parent_id,
                  name: item2.dept_name
                })
              }
            }
            for (let i of twoArr_) {
              if (item2.dept_id === i) {
                twoList.push({
                  dept_id: item2.dept_id,
                  children: [],
                  isOn: false,
                  parent_id: item2.parent_id,
                  name: item2.dept_name
                })
              }
            }
          })
        }
      })
      return twoList
    } catch (error) {
      console.warn(error)
    }
  },
  // 返回第三層
  handlejoinThree(treeList, threeArr, threeArr_) {
    try {
      const threeList = []
      treeList.forEach(item => {
        if (item.children.length > 0) {
          item.children.forEach(item2 => {
            if (item2.children.length > 0) {
              item2.children.forEach(item3 => {
                for (let i of threeArr) {
                  if (item3.dept_id === i) {
                    threeList.push({
                      dept_id: item3.dept_id,
                      isOn: true,
                      parent_id: item3.parent_id,
                      name: item3.dept_name
                    })
                  }
                }
                for (let i of threeArr_) {
                  if (item3.dept_id === i) {
                    threeList.push({
                      dept_id: item3.dept_id,
                      isOn: false,
                      parent_id: item3.parent_id,
                      name: item3.dept_name
                    })
                  }
                }
              })
            }
          })
        }
      })
      return threeList
    } catch (error) {
      console.warn(error)
    }
  },
  // 將數(shù)據(jù)的key恢復(fù)為原來的
  handleRestoreKey() {
    try {
      const treeList = this.handleJoinTree()
      // 去掉id后面的壹 貳 叁
      treeList.forEach(item1 => {
        item1.dept_id = item1.dept_id.replace('壹', '')
        if (item1.children.length > 0) {
          item1.children.forEach(item2 => {
            item2.dept_id = item2.dept_id.replace('貳', '')
            item2.parent_id = item2.parent_id.replace('壹', '')
            if (item2.children.length > 0) {
              item2.children.forEach(item3 => {
                item3.dept_id = item3.dept_id.replace('叁', '')
                item3.parent_id = item3.parent_id.replace('貳', '')
              })
            }
          })
        }
      })
      // 將dept_id字段轉(zhuǎn)為proj_id將dept_name字段轉(zhuǎn)為proj_name,將children轉(zhuǎn)為projs
      treeList.forEach(child1 => {
        if (child1.children.length > 0) {
          const childObj = child1.children.map(item => {
            let returnObj = {}
            if (item.children.length > 0) {
              const obj = item.children
              obj.children = obj.map(child2 => {
                return {
                  proj_id: child2.dept_id,
                  proj_name: child2.name
                }
              })
              returnObj = {
                dept_id: item.dept_id,
                dept_name: item.name,
                projs: obj.children
              }
            } else {
              returnObj = {
                projs: [],
                dept_id: item.dept_id,
                isOn: true,
                name: item.name
              }
            }
            return returnObj
          })
          child1.children = childObj
        }
      })
      console.log(treeList)
      return treeList
    } catch (error) {
      console.warn(error)
    }
  },
  // 詳情設(shè)置樹勾選
  handleSetTree(list) {
    try {
      console.log(list)
      const one = []
      const two = []
      const three = []
      if (list.length > 0) {
        // 第一層
        list.forEach(item => {
          let child = item.children || ''
          let obj = { id: item.dept_id + '壹', isOn: true }
          if (child && child.length > 0) {
            obj.isOn = false
          }
          one.push(obj)
        })
        // 第二層
        list.forEach(item1 => {
          let child1 = item1.children || ''
          if (child1 && child1.length > 0) {
            child1.forEach(item2 => {
              let child2 = item2.projs || ''
              let obj = { id: item2.dept_id + '貳', isOn: true }
              if (child2 && child2.length > 0) {
                obj.isOn = false
              }
              two.push(obj)
            })
          }
        })
        // 第二層
        list.forEach(item1 => {
          let child1 = item1.children || ''
          if (child1 && child1.length > 0) {
            child1.forEach(item2 => {
              let child2 = item2.projs || ''
              if (child2 && child2.length > 0) {
                child2.forEach(item3 => {
                  let obj = { id: item3.proj_id + '叁', isOn: true }
                  three.push(obj)
                })
              }
            })
          }
        })
        const tree = this.$refs.tree
        // 勾選第一層
        if (one && one.length > 0) {
          one.forEach(item => {
            let node = tree.getNode(item.id)
            if (item.isOn) {
              node.checked = true
              this.handleOneNode(true, node.data)
            } else {
              node.indeterminate = true
            }
          })
        }
        // 勾選第二層
        if (two && two.length > 0) {
          two.forEach(item => {
            let node = tree.getNode(item.id)
            if (item.isOn) {
              node.checked = true
              this.handleTwoNode(true, node.data)
            } else {
              node.indeterminate = true
            }
          })
        }
        // 勾選第三層
        if (three && three.length > 0) {
          three.forEach(item => {
            let node = tree.getNode(item.id)
            node.checked = true
          })
        }
      }
    } catch (error) {
      console.warn(error)
    }
  }
}

獲取轉(zhuǎn)換后的結(jié)構(gòu):

this.treeList = this.handleChangeKey(data)

提交轉(zhuǎn)換后的結(jié)構(gòu):

const treeList = this.handleRestoreKey()

5夜牡,總結(jié)


如果你有用到Tree組件与纽,且產(chǎn)品出的需求不咋地,可以看看Tree常用這些方法技巧塘装;

  • 獲取指定ID的節(jié)點(diǎn):this.$refs.tree.getNode(id)

  • 返回目前半選中的節(jié)點(diǎn)所組成的數(shù)組:this.$refs.tree.getHalfCheckedNodes()

  • 返回目前被選中的節(jié)點(diǎn)所組成的數(shù)組:this.$refs.tree.getCheckedNodes()

  • 通過 key / data 設(shè)置某個(gè)節(jié)點(diǎn)的勾選狀態(tài):this.$refs.tree.setChecked(id, true)


本次分享就到這兒啦急迂,我是@鵬多多,如果您看了覺得有幫助蹦肴,歡迎評(píng)論僚碎,關(guān)注,點(diǎn)贊冗尤,轉(zhuǎn)發(fā)听盖,我們下次見~

PS:在本頁按F12胀溺,在console中輸入document.querySelectorAll('._2VdqdF')[0].click()裂七,有驚喜哦

往期文章

個(gè)人主頁

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市无埃,隨后出現(xiàn)的幾起案子徙瓶,更是在濱河造成了極大的恐慌,老刑警劉巖嫉称,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侦镇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡织阅,警方通過查閱死者的電腦和手機(jī)壳繁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荔棉,“玉大人闹炉,你說我怎么就攤上這事∪笥#” “怎么了渣触?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)壹若。 經(jīng)常有香客問我嗅钻,道長(zhǎng)皂冰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任养篓,我火速辦了婚禮灼擂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘觉至。我一直安慰自己剔应,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布语御。 她就那樣靜靜地躺著峻贮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪应闯。 梳的紋絲不亂的頭發(fā)上纤控,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音碉纺,去河邊找鬼船万。 笑死,一個(gè)胖子當(dāng)著我的面吹牛骨田,可吹牛的內(nèi)容都是我干的耿导。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼态贤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼舱呻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悠汽,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤箱吕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后柿冲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茬高,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年假抄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了怎栽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡慨亲,死狀恐怖婚瓜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刑棵,我是刑警寧澤巴刻,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站蛉签,受9級(jí)特大地震影響胡陪,放射性物質(zhì)發(fā)生泄漏沥寥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一柠座、第九天 我趴在偏房一處隱蔽的房頂上張望邑雅。 院中可真熱鬧,春花似錦妈经、人聲如沸淮野。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽骤星。三九已至,卻和暖如春爆哑,著一層夾襖步出監(jiān)牢的瞬間洞难,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工揭朝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留队贱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓潭袱,卻偏偏與公主長(zhǎng)得像柱嫌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子敌卓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 首先來看看最終實(shí)現(xiàn)的效果: 這是一個(gè)搜索功能的分類字段慎式,此時(shí)暫時(shí)顯示的是兩層數(shù)據(jù)伶氢,會(huì)根據(jù)后端所傳遞的數(shù)據(jù)多層次渲染...
    夢(mèng)落隨心而飛閱讀 4,616評(píng)論 0 0
  • element-ui 目前基本成為前端pc網(wǎng)頁端標(biāo)準(zhǔn)ui框架趟径,但是目前element-ui研發(fā)團(tuán)隊(duì)已經(jīng)停止elem...
    蔣超_0920閱讀 6,585評(píng)論 0 2
  • 因?yàn)樽罱?xiàng)目需求,后臺(tái)接口返回樹結(jié)構(gòu)形式的數(shù)據(jù)癣防,頁面需要能夠勾選樹節(jié)點(diǎn)蜗巧,并且有且只能勾選一個(gè)。 看了eleme...
    多吃水果多鍛煉閱讀 3,791評(píng)論 0 1
  • 基礎(chǔ) 一蕾盯、屬性 1幕屹、props elementUI的樹指定了固定的數(shù)據(jù)格式,但是后臺(tái)返回的數(shù)據(jù)并不一致级遭,所以提供了...
    lesdom閱讀 5,522評(píng)論 0 1
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者望拖,不喜歡去冒險(xiǎn),但是人生放棄了冒險(xiǎn)挫鸽,也就放棄了無數(shù)的可能说敏。 ...
    yichen大刀閱讀 6,057評(píng)論 0 4