js无限层级, 递归遍历

来源数据结构

const productInfoList = [{
	productId: 2,
	productName: '2',
	parentId: 1
},{
	productId: 1,
	productName: '1',
	parentId: ''
},{
	productId: 3,
	productName: '3',
	parentId: 2
},{
	productId: 4,
	productName: '4',
	parentId: ''
}]
// ...无限层级,父子乱序

目标期望数据结构

const target = [{
	label: '1',
	id: 1,
	children: [{
		label: '2',
		id: 2,
		children: [{
			label: '3',
			id: 3,
			children: []
		}]
	}]
},{
	label: '4',
	id: 4,
	children: []
}]

业务逻辑

const infinite = (id, target = this.product.menu, source = productInfoList) => {
  for (const i in source) {
    if (source[i].parentId === id) {
      target.push({
        label: source[i].productName,
        id: source[i].productId,
        children: []
      })
      infinite(source[i].productId, target[target.length - 1].children)
    }
  }
}
infinite('') // 已知根节点id为 ''

// 无限层级,乱序数组,未知根节点

const source = [{
  productId: 2,
  name: '2',
  parentId: 1
}, {
  productId: 1,
  name: '1',
  parentId: 99
}, {
  productId: 4,
  name: '4',
  parentId: ''
}, {
  productId: 6,
  name: '6',
  parentId: 1
}, {
  productId: 3,
  name: '3',
  parentId: 1
}, {
  productId: 7,
  name: '7',
  parentId: 2
}, {
  productId: 8,
  name: '8',
  parentId: 66
}, {
  productId: 5,
  name: '5',
  parentId: 4
}]

const infiniteLevel = {
  init(source, formate) {
    this.target = [] // 用于临时存储结果
    this.source = source // 用户来源集合
    this.formateSub = formate || function() {} // 用户自定义格式化内容
    for (const index in this.source) {
      this.infinite(this.source[index], index) // 开始无限递归遍历,index参数用于判断是init执行的infinite还是自己递归执行的
    }
    return this.setResult() // 返回最终结果
  },
  formate(item) { // 用于格式化每一项,根据项目实际需求设置
    const sub = this.formateSub(item)
    return Object.assign({
      label: item.name,
      id: item.id,
      pid: item.pid,
      level: item.level || 0,
      children: item.children || []
    }, sub)
  },
  infinite(item, index) {
    const result = this.formate(item)
    if (index === undefined) result.level ++ // index用于判断level,如果有index就证明是第一次开始计算层级,如果是undefined就是递归来的叠加层级。
    let isParent = null
    const children = []
    this.source.forEach(s => {
      const formateS = this.formate(s)
      if (formateS.id === result.pid) isParent = s // 判断每一项的父级是否存在,由于来源中的id可能不存在,要先进行格式化。
      if (formateS.pid === result.pid) children.push(formateS) // 找到所有的同级
    })
    if (isParent) { // 如果父级存在继续递归向上寻找祖父级直至根级
      isParent.children = children // 将刚刚获取到的所有子集放入该父级节点下
      isParent.level = result.level // 新增level属性,用于判断该父级存在几级子节点,用于最后找到包含层级最多的父级,也就是根级。
      this.infinite(isParent)
    } else {
      this.target.push(result)
    }
  },
  setResult() {
    const result = []
    this.target.sort((a, b) => {
      return b.level - a.level
    }).forEach(e => {
      if (!result.some(r => r.id === e.id) && !isNaN(e.level)){
        result.push(e)
      }
    })
    return result
  }
}

console.log(infiniteLevel.init(source, (item) => {
  return {
    id: item.productId,
    pid: item.parentId
  }
}))
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用递归算法来遍历 jqgrid tree,按照层级顺序渲染。具体实现方法如下: 1. 首先,你需要确定 jqgrid tree 的数据结构。通常情况下,它是一个嵌套的 JSON 数组,每个节点都有一个唯一的 id 和一个 parent_id,指向它的父节点。 2. 接下来,你可以定义一个递归函数,用来遍历 jqgrid tree。该函数接受一个节点作为参数,并将该节点渲染到页面上。 3. 在递归函数中,你可以先渲染当前节点,然后递归遍历该节点的所有子节点。你可以使用 jQuery 的 each() 函数来遍历子节点,然后对每个子节点递归调用该函数。 4. 在渲染节点时,你可以根据节点的层级来设置缩进,以便更清晰地显示节点之间的层级关系。你可以使用 CSS 的 padding 属性来设置缩进。 下面是一个简单的示例代码,用来遍历 jqgrid tree 并按照层级顺序渲染: ```javascript function renderNode(node, level) { // 渲染当前节点 var html = '<tr><td style="padding-left: ' + level * 20 + 'px;">' + node.name + '</td></tr>'; $("#grid").append(html); // 遍历子节点 $.each(node.children, function(index, child) { renderNode(child, level + 1); }); } // 遍历 jqgrid tree $.each(data, function(index, node) { if (node.parent_id == null) { renderNode(node, 0); } }); ``` 在上面的示例代码中,renderNode() 函数用来渲染节点,它接受两个参数:节点对象和节点的层级。在遍历 jqgrid tree 时,我们使用 each() 函数来遍历每个根节点,并调用 renderNode() 函数来渲染整个树形结构。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值