在JavaScript中使用递归来渲染数据和创建嵌套列表项。

问题描述 投票:0回答:1

在我下面的代码中,我想在初始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个回答
0
投票

这有几个问题。

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

  • 你可以尝试添加 <li> 元素作为 <li> 元素。 他们真的需要一个 <ul><ol> 父母。 下面我们通过创建 <ul> 我们每个评论的孩子 <ul>s.

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

  • 你的数据很难区分,而且也没有真正的足够的数据来显示发生了什么。 下面的版本增加了一些节点,并给每个节点一个独特的 title. 我认为,这已经足够了,在显示嵌套结构的同时,不会让用户认为顺序嵌套是一个很好的选择。 正在发生。

  • 最重要的是,你的逻辑有一点歪曲。 你把一个对象传递给 createCommentListDOM 来构建,并将其作为parentId传递。该对象的id. 这就是为什么嵌套不能用的原因。 有几种方法可以解决这个问题。 我选择将父类的 节点 变成 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>
© www.soinside.com 2019 - 2024. All rights reserved.