MockData = { id: 1, name: "xiaoming", children: [ { id: 2, name: "xiaohonng2", children: [{ id: 5, name: " xiao5", children: [] }], }, { id: 3, name: " xiao3", children: [] }, { id: 4, name: " xiao4", children: [] }, ], }; function tarverse(nodes, id) { let result; for (let i = 0; i < nodes.length; i++) { if (nodes[i].id == id) { result = nodes[i]; return result; } if (nodes[i].children && nodes[i].children.length > 0) { result = tarverse(nodes[i].children, id); } if (result) return result; } return result; } let node = tarverse(MockData, 3); console.log(node, "node");
MockData = { id: 1, name: "xiaoming", children: [ { id: 2, name: "xiaohonng2", children: [{ id: 5, name: " xiao5", children: [] }], }, { id: 3, name: " xiao3", children: [] }, { id: 4, name: " xiao4", children: [] }, ], }; function tarverse(nodes, id) { let result = null; console.log(nodes) if (nodes.id == id) { result = nodes return result } if (nodes.children && nodes.children.length > 0) { for (let i = 0; i < nodes.children.length; i++) { result = tarverse(nodes.children[i], id) if (result) return result } } return result } let node = tarverse(MockData, 3); console.log(node, "node");
const traverse = (data, fn, childName = "children") => { if(fn(data)== false) { return false } if (data && data[childName]) { for(let i = 0; i < data[childName].length; i++) { if(!traverse(data[childName][i], fn, childName)) return false } } return true; };
---------------------------------- 以上是新版,下面的就不要看了 ---------------------------------------------
业务中,遍历一个东西,经常是,拿到一个对象,遍历他的一个 数组属性。
因为,遍历几乎都是针对数组的,只有数组,才会存放很多东西,需要遍历。
const traverse = (data, fn, childName = "children") => {
fn(data);
if (data && data[childName].length > 0) {
for(let i = 0; i < data[childName].length; i++) {
traverse(data[childName][i], fn, childName);
}
}
};
递归:
// dataTree 是 对象 childre 是数组
// *这个方法递归的现象是: 把第一个元素递归出来,然后再第一个元素的第一个子元素再递归出来,总之,看下面
// 1 1.1 1.1.1 1.1的子节点递归完了,就 1.1 1.1.2 1.1.2.1 。 即先把第一个尾部子节点,先递归出来。?
function bianli_digui(dataTree,childrenName = "children") {
for (let i = 0; i < dataTree.length; i++) {
if (dataTree[childrenName]&&dataTree[childrenName].length>0){
bianli_digui(dataTree[childrenName],childrenName)
}
}
}
待测试
方法二: 递归遍历,且可以传入Fn,不用,去改变里面的数组
var traverse = function traverse(data, fn, childrenName = "children") {
if (fn(data) === false) {
return false;
}
if (data && data[childrenName]) {
for (var i = 0 ; i <= data[childrenName].length - 1; i++) {
if (!traverse(data[childrenName][i], fn, childrenName)) return false;
}
}
return true;
};
注意了: 这里很重点,也是我想了很久才想到的。
tip:1. 之前发现这个是全递归,怎么中途找到想到的数据就结束呢?
2. 里面的return false 和 return true 有什么用,你会发现,你把全部return false删除掉也能 正常使用这个函数。
总结: 如果要找到数据,就推出整个递归循环,那么就要,你的Fn函数,最后返回 false就行了。
为什么: 1. fn(data)返回false,就进入了 if(fn(data)===false){ return false } 里面。
然后推出当前的递归,。
2. 退出当前递归后,来到 if(!traverse(xxxx))这里,如果为真,又return false,那么又退出当前递归。 然后如此循环,就会推出整个递归。
这里是工作中实际应用, 拿新的tree的数据, 用两个递归把 这个旧的tree 改成 新的tree
//* 拷贝并递归修改文件树数据,用res.Tree的结构 用DirectoryTree的数据
let My_DirectoryTree = _.cloneDeep(DirectoryTreeDatas)
CMFunc.traverseTree(res.Data, (resTree) => {
CMFunc.traverseTree(My_DirectoryTree, (myTree) => {
if (myTree.id === resTree.id) {
for (let key of Object.keys(myTree)) {
if (key == "content") {
resTree[key] = myTree[key]
}
}
}
})
})