在实际工做中,树形数据很常见,例如vue中的路由数据,系统菜单也是树形数据,组织管理也是树状的,DOM解构也是如此。例若有以下数据结构:vue
let tree = [
{
id:0,
name:'江西',
children:[
{ id:'01',name:'南昌',children:[]},
{ id:'02',name:'九江',children:[]}
]
},{
id:1,
name:'湖南',
children:[
{ id:'11',name:'长沙',children:[]},
{ id:'12',name:'衡阳',children:[]},
{ id:'13',name:'常德',children:[]},
]
}
]
复制代码
在理论上讲这种结构能够无限延伸。每一个节点下可能有children,children下可能还有children. 下面列举几种对上述结构操做的经常使用方法仅供参考:
(如下代码都是假如属性都是经过children字段进行拓展的,每一个对象惟一标识为id字段。)node
function flatTree(data) {
let result = []
for(let i = 0; i<data.length;i++){
let obj = {
id:data[i].id,
name:data[i].name
}
result.push(obj)
if (data[i]['children'] && data[i]['children'].length) {
result = result.concat(flatTree(data[i]['children']))
}
}
return result
}
// [{id:0,name:'江西'},{id:'01',name:'南昌'}...]
复制代码
function findNode(data,id) {
let result = []
for(let i = 0; i<data.length;i++){
if (data[i].id === id) {
result.push(data[i])
}
if (data[i]['children'] && data[i]['children'].length) {
result = result.concat(findNode(data[i]['children'],id))
}
}
return result
}
复制代码
经过查找某个id将返回一个数组结构,若是有id重复的,会返回全部重复的id对象数组数组
// 删除树操做
function deleteNode(data,id) {
for (let i =0;i<data.length;i++) {
if(data[i].id === id) {
data.splice(i,1)
i=i-1 // 防止有多个id相同状况下删除不干净
} else {
if (data[i]['children'] && data[i]['children'].length) {
deleteNode(data[i]['children'],id)
}else{
continue
}
}
}
return
}
复制代码
// 修改树
function updateNode(data,id,attr,callback) {
for(let i =0;i<data.length;i++) {
if(data[i].id === id) {
if (typeof callback == 'function') {
data[i][attr] = callback(data[i])
} else {
data[i][attr] = callback
}
continue
}
if (data[i]['children'] && data[i]['children'].length) {
updateNode(data[i]['children'],id,attr,callback)
}
}
}
复制代码
例如咱们须要往id=0节点增长一个属性enName:'江西',只须要:updateNode(tree,0,'enName','jiangxi') 假如咱们须要判断id=0节点下是否有children,若是有,咱们增长一个hasChild:true,因此callback参数也能够传入一个回调函数,第一个参数为当前节点bash
updateNode(tree,'12',0,(node)=>{
return node.children && node.children.length ? true:false
})
复制代码
function formPath(data,parentId=[]) {
for (let i = 0;i<data.length;i++) {
data[i].path = parentId.concat(data[i].id)
if(data[i].children && data[i].children.length){
formPath(data[i].children,data[i].path)
}
}
}
formPath(tree)
复制代码
function nodeMoveUpOrDown(data,id,flag=1) {
for(let i = 0;i<data.length;i++) {
if(data[i].id === id && flag === 1 && i!== data.length-1) {
const temp = data[i+1]
data[i+1] = data[i]
data[i] = temp
}
if(data[i].id === id && flag === 0 && i!== 0) {
const temp = data[i-1]
data[i-1] = data[i]
data[i] = temp
}
if(data[i].children && data[i].children.length) {
nodeMoveUpOrDown(data[i].children,id,flag)
}
}
}
复制代码
向上移动flag=0 向下移动flag=1数据结构
function nodeMove(data,current,target) {
let temp=[]
for(let i=0;i<data.length;i++){
if(data[i].id === current || data[i].id === target){
temp.push(i)
}
if(data[i].children && data[i].children.length){
nodeMove(data[i].children,current,target)
}
}
if(temp.length === 2){
let before = data[temp[0]]
data[temp[0]] = data[temp[1]]
data[temp[1]] = before
}
}
复制代码