在我下面的代码中,我想在初始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);
}
});
}
这有几个问题。
虽然它可能会或可能不会工作,但你可能不应该调用... ... 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>