当前位置:   article > 正文

Naive UI 获取树tree完整选中树结构(通用方法,也适用于其他自定义组件)_navie ui树形结构

navie ui树形结构

截止文章记录前,Naive UI 并未提供直接获取,与选中叶子节点相关的完整树结构数据方法,记录一下前端实现方法。

数据准备:

数据准备:树结构初始数据,选中相关的数据

  1. // 初始树结构数据
  2. let dataSetData = [
  3. {
  4. id: '1',
  5. text: '节点1',
  6. nodeuuid: '1',
  7. pnodeId: null,
  8. children: []
  9. },
  10. {
  11. id: '2',
  12. text: '节点2',
  13. nodeuuid: '2',
  14. pnodeId: null,
  15. children: [
  16. {
  17. id: '2-1',
  18. text: '节点2-1',
  19. nodeuuid: '2-1',
  20. pnodeId: '2',
  21. children: []
  22. },
  23. {
  24. id: '2-2',
  25. text: '节点2-2',
  26. nodeuuid: '2-2',
  27. pnodeId: '2',
  28. children: [
  29. {
  30. id: '2-2-1',
  31. text: '节点2-2-1',
  32. nodeuuid: '2-2-1',
  33. pnodeId: '2-2',
  34. children: []
  35. }
  36. ]
  37. },
  38. {
  39. id: '2-3',
  40. text: '节点2-3',
  41. nodeuuid: '2-3',
  42. pnodeId: '2',
  43. children: []
  44. }
  45. ]
  46. },
  47. {
  48. id: '3',
  49. text: '节点3',
  50. nodeuuid: '3',
  51. pnodeId: null,
  52. children: []
  53. },
  54. {
  55. id: '4',
  56. text: '节点4',
  57. nodeuuid: '4',
  58. pnodeId: null,
  59. children: []
  60. },
  61. {
  62. id: '5',
  63. text: '节点5',
  64. nodeuuid: '5',
  65. pnodeId: null,
  66. children: [
  67. {
  68. id: '5-1',
  69. text: '节点5-1',
  70. nodeuuid: '5-1',
  71. pnodeId: '5',
  72. children: []
  73. },
  74. {
  75. id: '5-2',
  76. text: '节点5-2',
  77. nodeuuid: '5-2',
  78. pnodeId: '5',
  79. children: []
  80. }
  81. ]
  82. }
  83. ]
  84. // 选中相关的数据
  85. let datasetCheckedNodes = [
  86. {
  87. id: '2',
  88. text: '节点2',
  89. nodeuuid: '2',
  90. pnodeId: null,
  91. children: [
  92. {
  93. id: '2-1',
  94. text: '节点2-1',
  95. nodeuuid: '2-1',
  96. pnodeId: '2',
  97. children: []
  98. },
  99. {
  100. id: '2-2',
  101. text: '节点2-2',
  102. nodeuuid: '2-2',
  103. pnodeId: '2',
  104. children: [
  105. {
  106. id: '2-2-1',
  107. text: '节点2-2-1',
  108. nodeuuid: '2-2-1',
  109. pnodeId: '2-2',
  110. children: []
  111. }
  112. ]
  113. },
  114. {
  115. id: '2-3',
  116. text: '节点2-3',
  117. nodeuuid: '2-3',
  118. pnodeId: '2',
  119. children: []
  120. }
  121. ]
  122. },
  123. {
  124. id: '2-3',
  125. text: '节点2-3',
  126. nodeuuid: '2-3',
  127. pnodeId: '2',
  128. children: []
  129. },
  130. {
  131. id: '2-2',
  132. text: '节点2-2',
  133. nodeuuid: '2-2',
  134. pnodeId: '2',
  135. children: [
  136. {
  137. id: '2-2-1',
  138. text: '节点2-2-1',
  139. nodeuuid: '2-2-1',
  140. pnodeId: '2-2',
  141. children: []
  142. }
  143. ]
  144. },
  145. {
  146. id: '2-2-1',
  147. text: '节点2-2-1',
  148. nodeuuid: '2-2-1',
  149. pnodeId: '2-2',
  150. children: []
  151. },
  152. {
  153. id: '4',
  154. text: '节点4',
  155. nodeuuid: '4',
  156. pnodeId: null,
  157. children: []
  158. },
  159. {
  160. id: '5-2',
  161. text: '节点5-2',
  162. nodeuuid: '5-2',
  163. pnodeId: '5',
  164. children: []
  165. }
  166. ]

 实现步骤,一共四步,如下: 

  1. // 0.设置每个节点唯一标识nodeuuid,相关父节点标识pnodeId(若初始树结构数据每个节点已有唯一标识,相关父节点标识,可跳过该步骤)
  2. // dataSetData = addParentData(res, null)
  3. // 1.设置相关树节点映射
  4. const treeMap = setMap()
  5. // 2.获取所有选中的叶子节点(目的是为了获取所有选中的叶子节点,可使用其他方法获得)
  6. const leafNodes = datasetCheckedNodes.filter(v => v && (!v.children || v.children.length == 0))
  7. // 3.获取所有和子节点相关,被勾选的根父节点集合(包含已勾选和未勾选数据,通过是否勾选标识区分)
  8. const rootNodes = getAllCheckedRootNodes(leafNodes, treeMap)
  9. // 4.删除未选中标识数据,获取重组后的完整树结构数据
  10. const treeData = getCheckedTree(rootNodes, leafNodes)
  11. console.log('重组后的完整树结构数据', treeData)

实现函数方法如下: 

  1. /**
  2. * 递归遍历赋值当前节点的父节点,设置每个节点唯一标识nodeuuid,相关父节点标识pnodeId
  3. * @param treeData 初始树结构数据
  4. * @param pnodeId 父节点Id
  5. * @returns treeData 处理后的树结构数据
  6. */
  7. function addParentData(treeData, pnodeId) {
  8. for (var i in treeData) {
  9. treeData[i].scopedSlots = {
  10. title: 'custom'
  11. }
  12. treeData[i].nodeuuid = uuidv4()
  13. treeData[i].text = treeData[i].text ? treeData[i].text : treeData[i].name
  14. treeData[i].pnodeId = pnodeId
  15. if (treeData[i].children && treeData[i].children.length) {
  16. addParentData(treeData[i].children, treeData[i].nodeuuid)
  17. }
  18. }
  19. return treeData
  20. }
  21. /**
  22. * 设置相关树节点映射
  23. * 两种方式:
  24. * 其一,树组件有提供快捷获取选中和半选数据的方法,可直接调用方法,组装treeMap(推荐)
  25. * 其二,树组件没有提供快捷获取选中和半选数据的方法,则递归所有初始树结构数据,组装treeMap(较消耗内存,慎用)
  26. * @returns treeMap 树节点映射
  27. */
  28. function setMap() {
  29. let treeMap = {} // 树节点映射
  30. // ----------------方法一(推荐)-------------------
  31. // 获取选中的数据
  32. // const checkedNodes = TreeRef.value.getCheckedData()
  33. // // 获取半选的数据
  34. // const indeterminateNodes = TreeRef.value.getIndeterminateData()
  35. // checkedNodes.options.forEach(node => {
  36. // if (node) {
  37. // treeMap[node.nodeuuid] = node
  38. // }
  39. // })
  40. // indeterminateNodes.options.forEach(node => {
  41. // if (node) {
  42. // treeMap[node.nodeuuid] = node
  43. // }
  44. // })
  45. // ------------------方法二(较消耗内存,慎用)-------------------
  46. treeMap = setMap2(dataSetData, treeMap)
  47. return treeMap
  48. }
  49. /**
  50. * 递归所有初始树结构数据,组装treeMap
  51. * @param {*} tree 初始树结构数据
  52. * @param {*} map
  53. * @returns
  54. */
  55. function setMap2(tree, map) {
  56. tree.forEach(node => {
  57. map[node.nodeuuid] = node
  58. if (node.children && node.children.length > 0) {
  59. setMap2(node.children, map)
  60. }
  61. })
  62. return map
  63. }
  64. /**
  65. * 获取所有和子节点相关,被勾选的根父节点集合(包含已勾选和未勾选数据,通过是否勾选标识区分)
  66. * @param leafCheckedNodes 所有选中的叶子节点
  67. * @param treeMap 相关树节点映射(勾选与半勾选)
  68. * @returns rootNodes 和子节点相关,被勾选的根父节点集合
  69. */
  70. function getAllCheckedRootNodes(leafCheckedNodes, treeMap) {
  71. let rootNodes = []
  72. leafCheckedNodes.forEach(node => {
  73. // 找到叶子结点的父节点
  74. let pNode = treeMap[node.pnodeId]
  75. // 迭代
  76. while (pNode) {
  77. // 添加已勾选的标志
  78. pNode.isChecked = true
  79. node = pNode
  80. pNode = treeMap[node.pnodeId]
  81. }
  82. // 如果pNode不存在,说明node是根节点
  83. if (!rootNodes.some(i => i.nodeuuid == node.nodeuuid)) {
  84. rootNodes.push(node)
  85. }
  86. })
  87. return rootNodes
  88. }
  89. /**
  90. * 删除未选中标识数据,递归获取重组后的完整树结构数据
  91. * @param rootNodes 跟勾选相关的根节点集合
  92. * @param checkedLeafNodes 所有选中的叶子节点
  93. * @returns
  94. */
  95. function getCheckedTree(rootNodes, checkedLeafNodes) {
  96. // 倒序,避免for循环中使用splice后导致index错乱
  97. for (let i = rootNodes.length - 1; i >= 0; i--) {
  98. const node = rootNodes[i]
  99. // 不是叶子节点
  100. if (node.children && node.children.length > 0) {
  101. // 检查勾选标志位,true,那么递归,false,那么删除
  102. if (node.isChecked) {
  103. getCheckedTree(node.children, checkedLeafNodes)
  104. } else {
  105. rootNodes.splice(i, 1)
  106. }
  107. } else {
  108. // 如果是叶子节点,那么检查其是否是勾选节点,是,保留,不是删除
  109. const flag = checkedLeafNodes.some(n => n.nodeuuid == node.nodeuuid)
  110. if (!flag) {
  111. rootNodes.splice(i, 1)
  112. }
  113. }
  114. }
  115. return rootNodes
  116. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号