javascript - 递归地在 ul 列表中显示 JavaScript 对象

标签 javascript html recursion

我正在尝试以 HTML ul 列表方式显示 JavaScript 对象。 该对象表示二叉树并具有以下格式:

{
    "val":2,
    "l":{
        "val":1,
        "l":{},
        "r":{}
    },
    "r":{
        "val":4,
        "l":{},
        "r":{
            "val":5,
            "l":{},
            "r":{}
        }
    }
}

我需要完成的结果是这样的:

<ul>
    <li>
        <a href="#">2</a>
        <ul>
            <li>
                <a href="#">1</a>
            </li>
            <li>
                <a href="#">4</a>
                <ul>
                    <li>
                        <a href="#">5</a>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

我在这里写这段代码是为了得到相应的结果字符串,但它没有生成正确的结果。

function buildList(data){
    var html = '';
    if(data.val){
        if(data.l){
            html += '<ul>';
            html += buildList(data.l);
        }
        html += '<li>';
        html += '<a href="#">' + data.val + '</a>'
        html += '</li>';
        if(data.r){
            html += buildList(data.r);
            html += '</ul>';
        }
    }

    return html;
}

任何猜测或线索将不胜感激。

最佳答案

让生活更轻松

在这种情况下,一点点数据抽象会走很长的路。如果您尝试在单个函数中处理数据中的所有差异,您将面临一大堆单分支 if 和其他副作用代码。

使用下面的数据抽象,我将复杂的逻辑和条件简化为单个 if/else 语句。我将逐步执行代码,然后在最后将它们放在一个可运行的演示中


一厢情愿

我不想考虑(例如)val 是否为 {} 或者 lr 是否具有有效值- 这对我来说毫无意义。我想写的是这样的:

const makeTree = ({val, l, r}) => {
  if (val === undefined)
    return []
  else
    return [Node('ul', Node('li', Link('#', val)), ...makeTree(l), ...makeTree(r))]
}

这假设我们有两个构造函数 NodeLink 可供我们使用。但在我们深入研究之前,我们看到 makeTree 无论如何都会返回一个数组。所以我们必须想出一个很好的面向用户的功能,以某种方式为我们将其构建到 HTML 中。那将是 makeMenu - 它所做的一切都是从数组中取出根节点并调用 .toElem()

const makeMenu = data =>
  makeTree(data)[0].toElem()

这也帮助我们知道我们需要 .toElem 在两种节点类型 NodeLink 上可用。看,用一厢情愿的想法构建你的程序很好,因为你想要的每一步都会告诉你接下来你必须构建的东西。


NodeLink 构造函数

现在让我们敲击 NodeLink。他们非常直截了当。 Node 只是一个特定 type 的通用 HTML 元素,它获取应用于它的子元素;请注意,每个 child 都应该有一个 .toElem 方法。 Link 只需要一个 href 和一些 text 并构造具有相应属性集的元素。

const Node = (type, ...children) => ({
  toElem: () => {
    const elem = document.createElement(type)
    children.forEach(child => elem.appendChild(child.toElem()))
    return elem
  }
})

const Link = (href, text) => ({
  toElem: () => {
    const elem = document.createElement('a')
    elem.setAttribute('href', href)
    elem.textContent = text
    return elem
  }
})

将它们放在一起

const Node = (type, ...children) => ({
  toElem: () => {
    const elem = document.createElement(type)
    children.forEach(child => elem.appendChild(child.toElem()))
    return elem
  }
})

const Link = (href, text) => ({
  toElem: () => {
    const elem = document.createElement('a')
    elem.setAttribute('href', href)
    elem.textContent = text
    return elem
  }
})

const makeTree = ({val, l, r}) => {
  if (val === undefined)
    return []
  else
    return [Node('ul', Node('li', Link('#', val)), ...makeTree(l), ...makeTree(r))]
}

const makeMenu = data =>
  makeTree(data)[0].toElem()

const data = { "val": 2, "l": { "val": 1, "l": {}, "r": {} }, "r": { "val": 4, "l": {}, "r": { "val": 5, "l": {}, "r": {} } } }

document.body.appendChild(makeMenu(data))

关于javascript - 递归地在 ul 列表中显示 JavaScript 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43550223/

相关文章:

html - 使一些菜单链接向右浮动,其他向左浮动

javascript - 如何在 HTML5 静音按钮中应用淡入淡出效果

c++ - 递归正弦函数

scala - 将普通递归转换为尾递归

javascript - ES6 React 属性未定义

javascript - 为什么这个 Javascript/HTML5 Canvas 不起作用?

javascript - 使用 Safari 和 HTML5 在 iPhone 上录音

javascript - 响应模式下底部背景位置错误

javascript - 使用 jQuery 根据一天中的时间更改 div

java - 将 for 循环更改为递归函数