【问题标题】:render data and create nested list item using recursion in JavaScript使用 JavaScript 中的递归呈现数据并创建嵌套列表项
【发布时间】:2020-09-28 09:10:33
【问题描述】:

在下面的代码中,我想在初始 DOM 内容加载时迭代嵌套数据,但问题是列表未附加到其父元素。我将父 ID 作为参数传递,但我无法找出问题所在,我正在使用递归方法来迭代数据请指导我解决问题。

const list_wrapper = document.querySelector("#list_wrapper");
let data = [
    {
        id: 1,
        title: "title 1",
        liked: false,
        comment: [{ id: 11, title: "title 1", liked: false, comment: [{ id: 111, title: "title 1", 
liked: false, comment: [{ id: 1111, title: "title 1", liked: false }] }] }],
    },
];
function createCommentListDOM(parEleID, comment) {
    const li = document.createElement("li");
    li.className = "list-group-item";
    li.setAttribute("id", comment.id);
    li.innerHTML = `${comment.title}`;
    if (document.getElementById(parEleID) == null) {
        list_wrapper.appendChild(li);
    } else {
        document.getElementById(parEleID).appendChild(li);
    }
}

// Initial DOM render ----------------
document.addEventListener("DOMContentLoaded", () => {
    iterateData(data);
});

function iterateData(arr) {
    arr.map((v) => {
        createCommentListDOM(v.id, v);
        if (v.comment != undefined) {
            return iterateData(v.comment);
        }
    });
}

【问题讨论】:

    标签: javascript list recursion dom


    【解决方案1】:

    这有几个问题:

    • 虽然它可能会或可能不会起作用,但您可能不应该在 内容加载 回调触发之前调用 querySelector。你用它来定义一个全局的list_wrapper 变量。在我下面的重写中,我们可以完全跳过这个变量。

    • 您尝试将<li> 元素添加为<li> 元素的子元素。他们真的需要<ul><ol> 父母。我们通过为每个评论<ul>s 创建<ul> 子级来处理此问题。

    • 你误用了map,这是关于将列表转换为其他列表的。这一点尤其明显,因为您的 map 回调在一个分支而不是另一个分支上返回结果。 当您想要的是创建 DOM 节点等副作用时,您可能应该改用forEach。 (map 仍然有效,但可能会让读者感到困惑。)

    • 您拥有难以区分的数据,并且不足以显示正在发生的事情。下面的版本增加了几个节点,并给每个节点一个不同的title。这已经足够了,我想展示嵌套结构,而不会让用户相信顺序嵌套是所有正在发生的事情。

    • 最重要的是,您的逻辑略有偏差。您将一个对象传递给createCommentListDOM 以进行构建,并将其作为 parentId 传递,拥有对象的 id。这就是嵌套不起作用的原因。有几种方法可以解决这个问题。我选择将父 node 传递到 iterateData 并从那里传递到 createCommentListDOM。这涉及从createCommentListDOM 返回容器,但这很容易。另一种方法是像你一样传递父 ID,但我发现这个版本更干净。

    所以这里有一个替代版本,主要使用您的代码,但进行了这些更改:

    function createCommentListDOM(parent, comment) {
        const li = document.createElement("li");
        li.className = "list-group-item";
        li.innerHTML = `${comment.title}`;
        li.setAttribute("id", comment.id);  // no longer needed?
        const ul = document.createElement("ul"); // need place for children
        li.appendChild(ul);
        parent.appendChild(li);
        return ul;
    }
    
    function iterateData(parent, arr) {
        arr.forEach ((v) => {  // not a `map` call
            const newParent = createCommentListDOM(parent, v);
            if (v.comment != undefined) {
                iterateData(newParent, v.comment);  // no `return` here
            }
        });
    }
    
    let data = [
      { id: 1, title: "title 1",  liked: false, comment: [
        { id: 11, title: "title 11", liked: false, comment: [
          { id: 111, title: "title 111", liked: false, comment: [
            { id: 1111, title: "title 1111", liked: false }
          ]},
          { id: 112, title: "title 112", liked: false},
          { id: 113, title: "title 113", liked: false}
        ]}
      ]}, 
      { id: 2, title: "title 2", liked: false, comment: [
        { id: 21, title: "title 21", liked: false }
      ]}
    ];
    
    document.addEventListener("DOMContentLoaded", () => {
      // should probably not call querySelector before content loaded
      iterateData(document.querySelector("#list_wrapper"), data); 
    });
    <ul id="list_wrapper"></ul>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多