截止文章記錄前,Naive UI 并未提供直接獲取,與選中葉子節(jié)點相關(guān)的完整樹結(jié)構(gòu)數(shù)據(jù)方法,記錄一下前端實現(xiàn)方法。
數(shù)據(jù)準備:
數(shù)據(jù)準備:樹結(jié)構(gòu)初始數(shù)據(jù),選中相關(guān)的數(shù)據(jù)
// 初始樹結(jié)構(gòu)數(shù)據(jù)
let dataSetData = [
{
id: '1',
text: '節(jié)點1',
nodeuuid: '1',
pnodeId: null,
children: []
},
{
id: '2',
text: '節(jié)點2',
nodeuuid: '2',
pnodeId: null,
children: [
{
id: '2-1',
text: '節(jié)點2-1',
nodeuuid: '2-1',
pnodeId: '2',
children: []
},
{
id: '2-2',
text: '節(jié)點2-2',
nodeuuid: '2-2',
pnodeId: '2',
children: [
{
id: '2-2-1',
text: '節(jié)點2-2-1',
nodeuuid: '2-2-1',
pnodeId: '2-2',
children: []
}
]
},
{
id: '2-3',
text: '節(jié)點2-3',
nodeuuid: '2-3',
pnodeId: '2',
children: []
}
]
},
{
id: '3',
text: '節(jié)點3',
nodeuuid: '3',
pnodeId: null,
children: []
},
{
id: '4',
text: '節(jié)點4',
nodeuuid: '4',
pnodeId: null,
children: []
},
{
id: '5',
text: '節(jié)點5',
nodeuuid: '5',
pnodeId: null,
children: [
{
id: '5-1',
text: '節(jié)點5-1',
nodeuuid: '5-1',
pnodeId: '5',
children: []
},
{
id: '5-2',
text: '節(jié)點5-2',
nodeuuid: '5-2',
pnodeId: '5',
children: []
}
]
}
]
// 選中相關(guān)的數(shù)據(jù)
let datasetCheckedNodes = [
{
id: '2',
text: '節(jié)點2',
nodeuuid: '2',
pnodeId: null,
children: [
{
id: '2-1',
text: '節(jié)點2-1',
nodeuuid: '2-1',
pnodeId: '2',
children: []
},
{
id: '2-2',
text: '節(jié)點2-2',
nodeuuid: '2-2',
pnodeId: '2',
children: [
{
id: '2-2-1',
text: '節(jié)點2-2-1',
nodeuuid: '2-2-1',
pnodeId: '2-2',
children: []
}
]
},
{
id: '2-3',
text: '節(jié)點2-3',
nodeuuid: '2-3',
pnodeId: '2',
children: []
}
]
},
{
id: '2-3',
text: '節(jié)點2-3',
nodeuuid: '2-3',
pnodeId: '2',
children: []
},
{
id: '2-2',
text: '節(jié)點2-2',
nodeuuid: '2-2',
pnodeId: '2',
children: [
{
id: '2-2-1',
text: '節(jié)點2-2-1',
nodeuuid: '2-2-1',
pnodeId: '2-2',
children: []
}
]
},
{
id: '2-2-1',
text: '節(jié)點2-2-1',
nodeuuid: '2-2-1',
pnodeId: '2-2',
children: []
},
{
id: '4',
text: '節(jié)點4',
nodeuuid: '4',
pnodeId: null,
children: []
},
{
id: '5-2',
text: '節(jié)點5-2',
nodeuuid: '5-2',
pnodeId: '5',
children: []
}
]
?實現(xiàn)步驟,一共四步,如下:?文章來源:http://www.zghlxwxcb.cn/news/detail-849638.html
// 0.設(shè)置每個節(jié)點唯一標識nodeuuid,相關(guān)父節(jié)點標識pnodeId(若初始樹結(jié)構(gòu)數(shù)據(jù)每個節(jié)點已有唯一標識,相關(guān)父節(jié)點標識,可跳過該步驟)
// dataSetData = addParentData(res, null)
// 1.設(shè)置相關(guān)樹節(jié)點映射
const treeMap = setMap()
// 2.獲取所有選中的葉子節(jié)點(目的是為了獲取所有選中的葉子節(jié)點,可使用其他方法獲得)
const leafNodes = datasetCheckedNodes.filter(v => v && (!v.children || v.children.length == 0))
// 3.獲取所有和子節(jié)點相關(guān),被勾選的根父節(jié)點集合(包含已勾選和未勾選數(shù)據(jù),通過是否勾選標識區(qū)分)
const rootNodes = getAllCheckedRootNodes(leafNodes, treeMap)
// 4.刪除未選中標識數(shù)據(jù),獲取重組后的完整樹結(jié)構(gòu)數(shù)據(jù)
const treeData = getCheckedTree(rootNodes, leafNodes)
console.log('重組后的完整樹結(jié)構(gòu)數(shù)據(jù)', treeData)
實現(xiàn)函數(shù)方法如下:?文章來源地址http://www.zghlxwxcb.cn/news/detail-849638.html
/**
* 遞歸遍歷賦值當前節(jié)點的父節(jié)點,設(shè)置每個節(jié)點唯一標識nodeuuid,相關(guān)父節(jié)點標識pnodeId
* @param treeData 初始樹結(jié)構(gòu)數(shù)據(jù)
* @param pnodeId 父節(jié)點Id
* @returns treeData 處理后的樹結(jié)構(gòu)數(shù)據(jù)
*/
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
}
/**
* 設(shè)置相關(guān)樹節(jié)點映射
* 兩種方式:
* 其一,樹組件有提供快捷獲取選中和半選數(shù)據(jù)的方法,可直接調(diào)用方法,組裝treeMap(推薦)
* 其二,樹組件沒有提供快捷獲取選中和半選數(shù)據(jù)的方法,則遞歸所有初始樹結(jié)構(gòu)數(shù)據(jù),組裝treeMap(較消耗內(nèi)存,慎用)
* @returns treeMap 樹節(jié)點映射
*/
function setMap() {
let treeMap = {} // 樹節(jié)點映射
// ----------------方法一(推薦)-------------------
// 獲取選中的數(shù)據(jù)
// const checkedNodes = TreeRef.value.getCheckedData()
// // 獲取半選的數(shù)據(jù)
// 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
// }
// })
// ------------------方法二(較消耗內(nèi)存,慎用)-------------------
treeMap = setMap2(dataSetData, treeMap)
return treeMap
}
/**
* 遞歸所有初始樹結(jié)構(gòu)數(shù)據(jù),組裝treeMap
* @param {*} tree 初始樹結(jié)構(gòu)數(shù)據(jù)
* @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
}
/**
* 獲取所有和子節(jié)點相關(guān),被勾選的根父節(jié)點集合(包含已勾選和未勾選數(shù)據(jù),通過是否勾選標識區(qū)分)
* @param leafCheckedNodes 所有選中的葉子節(jié)點
* @param treeMap 相關(guān)樹節(jié)點映射(勾選與半勾選)
* @returns rootNodes 和子節(jié)點相關(guān),被勾選的根父節(jié)點集合
*/
function getAllCheckedRootNodes(leafCheckedNodes, treeMap) {
let rootNodes = []
leafCheckedNodes.forEach(node => {
// 找到葉子結(jié)點的父節(jié)點
let pNode = treeMap[node.pnodeId]
// 迭代
while (pNode) {
// 添加已勾選的標志
pNode.isChecked = true
node = pNode
pNode = treeMap[node.pnodeId]
}
// 如果pNode不存在,說明node是根節(jié)點
if (!rootNodes.some(i => i.nodeuuid == node.nodeuuid)) {
rootNodes.push(node)
}
})
return rootNodes
}
/**
* 刪除未選中標識數(shù)據(jù),遞歸獲取重組后的完整樹結(jié)構(gòu)數(shù)據(jù)
* @param rootNodes 跟勾選相關(guān)的根節(jié)點集合
* @param checkedLeafNodes 所有選中的葉子節(jié)點
* @returns
*/
function getCheckedTree(rootNodes, checkedLeafNodes) {
// 倒序,避免for循環(huán)中使用splice后導(dǎo)致index錯亂
for (let i = rootNodes.length - 1; i >= 0; i--) {
const node = rootNodes[i]
// 不是葉子節(jié)點
if (node.children && node.children.length > 0) {
// 檢查勾選標志位,true,那么遞歸,false,那么刪除
if (node.isChecked) {
getCheckedTree(node.children, checkedLeafNodes)
} else {
rootNodes.splice(i, 1)
}
} else {
// 如果是葉子節(jié)點,那么檢查其是否是勾選節(jié)點,是,保留,不是刪除
const flag = checkedLeafNodes.some(n => n.nodeuuid == node.nodeuuid)
if (!flag) {
rootNodes.splice(i, 1)
}
}
}
return rootNodes
}
到了這里,關(guān)于Naive UI 獲取樹tree完整選中樹結(jié)構(gòu)(通用方法,也適用于其他自定義組件)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!