赞
踩
截止文章记录前,Naive UI 并未提供直接获取,与选中叶子节点相关的完整树结构数据方法,记录一下前端实现方法。
数据准备:
数据准备:树结构初始数据,选中相关的数据
- // 初始树结构数据
- let dataSetData = [
- {
- id: '1',
- text: '节点1',
- nodeuuid: '1',
- pnodeId: null,
- children: []
- },
- {
- id: '2',
- text: '节点2',
- nodeuuid: '2',
- pnodeId: null,
- children: [
- {
- id: '2-1',
- text: '节点2-1',
- nodeuuid: '2-1',
- pnodeId: '2',
- children: []
- },
- {
- id: '2-2',
- text: '节点2-2',
- nodeuuid: '2-2',
- pnodeId: '2',
- children: [
- {
- id: '2-2-1',
- text: '节点2-2-1',
- nodeuuid: '2-2-1',
- pnodeId: '2-2',
- children: []
- }
- ]
- },
- {
- id: '2-3',
- text: '节点2-3',
- nodeuuid: '2-3',
- pnodeId: '2',
- children: []
- }
- ]
- },
- {
- id: '3',
- text: '节点3',
- nodeuuid: '3',
- pnodeId: null,
- children: []
- },
- {
- id: '4',
- text: '节点4',
- nodeuuid: '4',
- pnodeId: null,
- children: []
- },
- {
- id: '5',
- text: '节点5',
- nodeuuid: '5',
- pnodeId: null,
- children: [
- {
- id: '5-1',
- text: '节点5-1',
- nodeuuid: '5-1',
- pnodeId: '5',
- children: []
- },
- {
- id: '5-2',
- text: '节点5-2',
- nodeuuid: '5-2',
- pnodeId: '5',
- children: []
- }
- ]
- }
- ]
-
- // 选中相关的数据
- let datasetCheckedNodes = [
- {
- id: '2',
- text: '节点2',
- nodeuuid: '2',
- pnodeId: null,
- children: [
- {
- id: '2-1',
- text: '节点2-1',
- nodeuuid: '2-1',
- pnodeId: '2',
- children: []
- },
- {
- id: '2-2',
- text: '节点2-2',
- nodeuuid: '2-2',
- pnodeId: '2',
- children: [
- {
- id: '2-2-1',
- text: '节点2-2-1',
- nodeuuid: '2-2-1',
- pnodeId: '2-2',
- children: []
- }
- ]
- },
- {
- id: '2-3',
- text: '节点2-3',
- nodeuuid: '2-3',
- pnodeId: '2',
- children: []
- }
- ]
- },
- {
- id: '2-3',
- text: '节点2-3',
- nodeuuid: '2-3',
- pnodeId: '2',
- children: []
- },
- {
- id: '2-2',
- text: '节点2-2',
- nodeuuid: '2-2',
- pnodeId: '2',
- children: [
- {
- id: '2-2-1',
- text: '节点2-2-1',
- nodeuuid: '2-2-1',
- pnodeId: '2-2',
- children: []
- }
- ]
- },
- {
- id: '2-2-1',
- text: '节点2-2-1',
- nodeuuid: '2-2-1',
- pnodeId: '2-2',
- children: []
- },
- {
- id: '4',
- text: '节点4',
- nodeuuid: '4',
- pnodeId: null,
- children: []
- },
- {
- id: '5-2',
- text: '节点5-2',
- nodeuuid: '5-2',
- pnodeId: '5',
- children: []
- }
- ]

实现步骤,一共四步,如下:
- // 0.设置每个节点唯一标识nodeuuid,相关父节点标识pnodeId(若初始树结构数据每个节点已有唯一标识,相关父节点标识,可跳过该步骤)
- // dataSetData = addParentData(res, null)
- // 1.设置相关树节点映射
- const treeMap = setMap()
- // 2.获取所有选中的叶子节点(目的是为了获取所有选中的叶子节点,可使用其他方法获得)
- const leafNodes = datasetCheckedNodes.filter(v => v && (!v.children || v.children.length == 0))
- // 3.获取所有和子节点相关,被勾选的根父节点集合(包含已勾选和未勾选数据,通过是否勾选标识区分)
- const rootNodes = getAllCheckedRootNodes(leafNodes, treeMap)
- // 4.删除未选中标识数据,获取重组后的完整树结构数据
- const treeData = getCheckedTree(rootNodes, leafNodes)
-
- console.log('重组后的完整树结构数据', treeData)
实现函数方法如下:
- /**
- * 递归遍历赋值当前节点的父节点,设置每个节点唯一标识nodeuuid,相关父节点标识pnodeId
- * @param treeData 初始树结构数据
- * @param pnodeId 父节点Id
- * @returns treeData 处理后的树结构数据
- */
- function addParentData(treeData, pnodeId) {
- for (var i in treeData) {
- treeData[i].scopedSlots = {
- title: 'custom'
- }
- treeData[i].nodeuuid = uuidv4()
- treeData[i].text = treeData[i].text ? treeData[i].text : treeData[i].name
- treeData[i].pnodeId = pnodeId
-
- if (treeData[i].children && treeData[i].children.length) {
- addParentData(treeData[i].children, treeData[i].nodeuuid)
- }
- }
- return treeData
- }
-
- /**
- * 设置相关树节点映射
- * 两种方式:
- * 其一,树组件有提供快捷获取选中和半选数据的方法,可直接调用方法,组装treeMap(推荐)
- * 其二,树组件没有提供快捷获取选中和半选数据的方法,则递归所有初始树结构数据,组装treeMap(较消耗内存,慎用)
- * @returns treeMap 树节点映射
- */
- function setMap() {
- let treeMap = {} // 树节点映射
- // ----------------方法一(推荐)-------------------
- // 获取选中的数据
- // const checkedNodes = TreeRef.value.getCheckedData()
- // // 获取半选的数据
- // const indeterminateNodes = TreeRef.value.getIndeterminateData()
-
- // checkedNodes.options.forEach(node => {
- // if (node) {
- // treeMap[node.nodeuuid] = node
- // }
- // })
- // indeterminateNodes.options.forEach(node => {
- // if (node) {
- // treeMap[node.nodeuuid] = node
- // }
- // })
-
- // ------------------方法二(较消耗内存,慎用)-------------------
- treeMap = setMap2(dataSetData, treeMap)
-
- return treeMap
- }
-
- /**
- * 递归所有初始树结构数据,组装treeMap
- * @param {*} tree 初始树结构数据
- * @param {*} map
- * @returns
- */
- function setMap2(tree, map) {
- tree.forEach(node => {
- map[node.nodeuuid] = node
- if (node.children && node.children.length > 0) {
- setMap2(node.children, map)
- }
- })
-
- return map
- }
-
- /**
- * 获取所有和子节点相关,被勾选的根父节点集合(包含已勾选和未勾选数据,通过是否勾选标识区分)
- * @param leafCheckedNodes 所有选中的叶子节点
- * @param treeMap 相关树节点映射(勾选与半勾选)
- * @returns rootNodes 和子节点相关,被勾选的根父节点集合
- */
- function getAllCheckedRootNodes(leafCheckedNodes, treeMap) {
- let rootNodes = []
- leafCheckedNodes.forEach(node => {
- // 找到叶子结点的父节点
- let pNode = treeMap[node.pnodeId]
- // 迭代
- while (pNode) {
- // 添加已勾选的标志
- pNode.isChecked = true
- node = pNode
- pNode = treeMap[node.pnodeId]
- }
- // 如果pNode不存在,说明node是根节点
- if (!rootNodes.some(i => i.nodeuuid == node.nodeuuid)) {
- rootNodes.push(node)
- }
- })
- return rootNodes
- }
-
- /**
- * 删除未选中标识数据,递归获取重组后的完整树结构数据
- * @param rootNodes 跟勾选相关的根节点集合
- * @param checkedLeafNodes 所有选中的叶子节点
- * @returns
- */
- function getCheckedTree(rootNodes, checkedLeafNodes) {
- // 倒序,避免for循环中使用splice后导致index错乱
- for (let i = rootNodes.length - 1; i >= 0; i--) {
- const node = rootNodes[i]
- // 不是叶子节点
- if (node.children && node.children.length > 0) {
- // 检查勾选标志位,true,那么递归,false,那么删除
- if (node.isChecked) {
- getCheckedTree(node.children, checkedLeafNodes)
- } else {
- rootNodes.splice(i, 1)
- }
- } else {
- // 如果是叶子节点,那么检查其是否是勾选节点,是,保留,不是删除
- const flag = checkedLeafNodes.some(n => n.nodeuuid == node.nodeuuid)
- if (!flag) {
- rootNodes.splice(i, 1)
- }
- }
- }
- return rootNodes
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。