前端数据映射—>平铺
1.树形结构的映射
const data = [{
id:1,
name:'1',
children:[
{
id:2,
name:'1-1',
children:[
{
id:3,
name:"1-1-1"
},
{
id:4,
name:"1-1-2",
children:[
{
id:5,
name:"1-1-2-1"
}
]
}
]
}
]
},
{
id:6,
name:'2',
children:[
{
id:7,
name:'2-1',
children:[
{
id:8,
name:"2-1-1"
},
{
id:9,
name:"2-1-2"
},
]
}
]
}
]
// 这里的主要工作就是数据平铺,以及加个索引,类似于后台数据库中的索引吧,方便快速查找
const floatMap = (data)=>{
let key = 0;
const float = (data,parent)=>{
return data.reduce((obj,currentNode)=>{
currentNode.key = key;
obj[key] = {
parent,
node: currentNode
}
key ++ ;
if (currentNode.children) {
obj= {...obj,...float(currentNode.children,currentNode)}
}
return obj
},{})
}
return float(data);
}
// 得出的结果大概就是 我们起个名字叫MappingData,
MappingData = {
0:{node:{id:1,name:'1',key:0,children:[xxxx]}},
1:{node:{id:2,name:'1-1',key:1,children:[xxxx]}},
}
// 此时源数据的每一个item上也会又一个key 属性
给这个Tree树添加checked,我们都知道一般的树组件都有这个功能,当选中父亲时,所有的儿子都要选中,当所有的儿子选中时,父亲也自动选中;
// 当用户选择一个节点时,我们要有两个动作,
// 一个是向下递归,选择它所有儿子节点,
// 二是然后在向上递归,查看它是否(所在层)的儿子都是选中状态
// 这里为什么是所在层呢,
// 比如说:本层的children 里面的item项,如果item项里面所有的item子孙都是选中的,那么item也会自动选中,如果没有一箱没有选中,那item也就没有选中,所以父亲只需要判断自己的children是否都是选中状态即可
1.先说向下递归 方法就叫checkDown吧,
// 1.这里的item 项表示选中的某一项,2.checked表示当前是要选中还是不选中也就是true和false
const checkDown = (item,checked)=>{
//1.首先更改自己,给自己添加一个属性, 同样会使 MappingData 中的node 数据改变会增加key 属性
item.checked = checked;
if(item.children){
item.children.forEach(i=>checkDown(i,checked))
}
}
2.向上递归,这里就会用到我们的MappingData,映射后得到的数据
// 1.这里的item 项表示选中的某一项,2.checked表示当前是要选中还是不选中也就是true和false
const checkUp = (item,checked)=>{
// 向上递归自然要找到父节点,如果快速找到父节点,这里就用到了MappingData,因为用它就不需要循环查找
// MappingData数据结构例如:{0:{node:{},parent:{}}},这里的0 ,也就是item中的key;
// 这样就找到了第一层级的父亲parent
const parent = MappingData[item.key].parent
//父亲是否需要选中,要看它下一层级的儿子是否都选中
// 因为这里还需要找到父亲的父亲,还要继续网上查找,所以这里要用到递归
if(checked ){
parent.checked = parent.children.every(i=>i.checked)
}else{
parent.checked = false
}
// 因为这里还需要找到父亲的父亲,还要继续网上查找,所以这里要用到递归
checkUp(parent,checked)
}
这里如果是vue 的话,就不需要管了,因为vue 是响应式的,会自动更新
如果是react 的还要setDate 一下,
因为react 更新数据要是一个全新的数据,这里我们可以使用:
this.setState({
TreeDate:data.slice(0)
})
// 如果用的是hooks
setTreeData(data.slice(0))
这里的映射数据(并且铺平)还有一个什么好处呢,那就是只管获取数据
1.比如要我要拿到所有选中的节点,那要是没有映射表的话,那只能递归去寻找了
2.因为我们这里用到了平铺并且建立了索引
我们只需要
const checkedArray = Object.values(MappingData).map(i=>{
return i.node.checked
})
很方便即可拿到我们所选中的数据