snippet
大约 2 分钟react
数组 To 树形
/**
* 数组转树形结构
* @param {array} arr 被转换的数组
* @param {number|string} root 根节点(最外层节点)
* @returns array
*/
function arrayToTreeV3(arr, rootVal, fieldConfig) {
return arr.filter(item => item[fieldConfig.pid] === rootVal).map(item => ({ ...item, children: arrayToTreeV3(arr, item[fieldConfig.id], fieldConfig) }))
}
// 测试用数据
const menuItems = [
{id:1, name:'根节点',pid:0},
{id:2, name:'一级子节点01',pid:1,},
{id:3, name:'一级子节点02',pid:1,},
{id:4, name:'二级子节点01',pid:2,},
]
// 数组中对象的关键字段描述
const fieldConfig = {
id: 'id', // 主键字段=唯一字段
pid: 'pid', // 所属上级的字段
}
const root = arrayToTreeV3(menuItems,0,fieldConfig)
console.log(root)
树形转换为数组
// 测试用数据
const treeData = [
{
id:1000,label:'江苏',children:[
{id:1001,label:'徐州',children:[
{id:100101,label:'泉山区'},{id:100102,label:'云龙区'},{id:100103,label:'鼓楼区'},{id:100104,label:'九里区'},{id:100105,label:'铜山区'}
]},
{id:1002,label:'南京'},
{id:1003,label:'苏州',children:[
{id:100301,label:'常熟'},{id:100302,label:'昆山'},{id:100303,label:'张家港'},{id:100304,label:'吴江'},{id:100305,label:'姑苏区'},{id:100306,label:'平江区'}
]},
]
},
{id:2000,label:'浙江'},
{
id:3000,label:'上海',children:[
{id:3001,label:'静安区'},{id:3002,label:'浦东区'},{id:3003,label:'徐汇区'},{id:3004,label:'青浦区'},
]}
]
// 将树形数据转换为数组
// treeData: 树形结构数组(node组成的数组)
// fieldConfig:字段映射表,3个属性id,pid,children依次表示node的主键,上级字段,子节点属性
// pid:本节点的上级节点(父级节点的主键,第一次调用时传入0)
// nodeArr:node最终形成的数组,初次调用时传入空数组
function tree2Arr(treeData,fieldConfig,pid,nodeArr){
if(!treeData || treeData.length === 0 ) return null
for(const node of treeData){
if(!node) continue
const childrenNodes = node[fieldConfig.children]
if(childrenNodes && childrenNodes.length > 0){
const childrenNodesCoped = JSON.parse(JSON.stringify(childrenNodes))
delete node[fieldConfig.children]
tree2Arr(childrenNodesCoped,fieldConfig,node[fieldConfig.id],nodeArr)
}
node[fieldConfig.pid] = pid
nodeArr.push(node)
}
}
// 测试
function test02(){
const arr = []
const fieldConfig = {id:'id', pid:'pid',children:'children'}
tree2Arr(treeData,fieldConfig,0,arr)
console.log('树形数据转换后的数组:', arr)
}
遍历树形数据返回节点对象
treeData 是树形数据节点构成的数组(没有一个根节点的树形结构数据),遍历树形结构时对比属性 fieldName 的值等于 fieldVal 的节点,返回给调用者
console.log('tree.js')
const treeData = [
{
id:1000,label:'江苏',children:[
{id:1001,label:'徐州',children:[
{id:100101,label:'泉山区'},{id:100102,label:'云龙区'},{id:100103,label:'鼓楼区'},{id:100104,label:'九里区'},{id:100105,label:'铜山区'}
]},
{id:1002,label:'南京'},
{id:1003,label:'苏州',children:[
{id:100301,label:'常熟'},{id:100302,label:'昆山'},{id:100303,label:'张家港'},{id:100304,label:'吴江'},{id:100305,label:'姑苏区'},{id:100306,label:'平江区'}
]},
]
},
{id:2000,label:'浙江'},
{
id:3000,label:'上海',children:[
{id:3001,label:'静安区'},{id:3002,label:'浦东区'},{id:3003,label:'徐汇区'},{id:3004,label:'青浦区'},
]}
]
// 默认下级属性:children
function getNode8Attr(treeNodeList, fieldName, fieldVal){
if(!treeNodeList || treeNodeList.length === 0) return null
for(const node of treeNodeList){
const match = node[fieldName] == fieldVal
if(match) return node
const children = node.children || []
let node01 = null
if(children.length !== 0) node01 = getNode8Attr(children, fieldName, fieldVal)
if(node01) return node01
}
return null
}
function test01(){
const retNode = getNode8Attr(treeData,'label','浙江')
console.log('遍历树形得到的节点是:',retNode)
}
