javascript - 仅获取数组的一个元素及其子元素
问题描述
我有一个多维数组categories
,我正在用menuToElement
函数循环这个数组。
它接受 alarray
及其子元素的元素并在 a 中返回它ul
。代码完全可以工作,但我不知道如何只循环数组的一个元素及其所有子元素。
例如,我想要做的是仅循环引擎元素及其所有子元素和所有子数组。我的问题是:这是否可能与我正在使用的for...of
循环一起使用,因为我尝试循环遍历类别的索引并且它说它是不可迭代的。
function menuToElement(menu) {
const ul = document.createElement("ul");
for (const item of menu) {
const li = document.createElement("li");
if (Object(item) === item) {
li.textContent = item.text + ' \u25BD';
li.appendChild(menuToElement(item.children));
} else {
li.textContent = item;
}
ul.appendChild(li);
}
return ul;
}
var categories = [{
text: "engine",
children: [1, 2, 3, {
text: "piston",
children: [4, 5, 6, {
text: "piston",
children: [4, 5, 6]
}]
}]
}, {
text: "tire",
children: [7, 8, 9]
}];
const ul = menuToElement(categories);
document.getElementById("menu").appendChild(ul);
li>ul {
display: none;
}
li:hover>ul {
display: block;
}
<div id="menu"></div>
解决方案
首先,我们从一些让我们的生活更轻松的助手开始:elem
和text
-
const elem = (tag, ...children) =>
{ const node = document.createElement(tag)
children.forEach(node.appendChild.bind(node))
return node
}
const text =
document.createTextNode.bind(document)
const doc =
elem
( "article" // <article>
, elem("p", text("wash hand")) // <p>wash hand</p>
, elem("p", text("read book")) // <p>read book</p>
, elem("p", text("stay safe")) // <p>stay safe</p>
) // </article>
document.body.appendChild(doc)
article { border: 1px solid tomato; }
p { border: 1px solid dodgerblue; }
接下来我们定义如何将一个菜单项转换为一个菜单节点,toMenu1
-
- 如果输入
item
是一个对象,返回一个LI
with并item.text
调用toMenu
item.children
- 否则(通过归纳)输入不是
item
对象。在这种情况下,只需返回一个纯文本LI
const toMenu1 = (item = {}) =>
Object(item) === item
? elem('li', text(`${item.text} \u25BD`), toMenu(item.children)) // 1
: elem('li', text(item)) // 2
我们还没有写toMenu
,但在上面我们看到它需要一个项目数组。编写这个函数比上一个更容易 -
- 返回
UL
每个项目使用转换的位置toMenu1
const toMenu = (all = []) =>
elem('ul', ...all.map(toMenu1)) // 1
在我们继续之前,展开下面的代码片段以在您自己的浏览器中验证结果 -
const elem = (tag, ...children) =>
{ const node = document.createElement(tag)
children.forEach(node.appendChild.bind(node))
return node
}
const text =
document.createTextNode.bind(document)
const toMenu1 = (item = {}) =>
Object(item) === item
? elem('li', text(`${item.text} \u25BD`), toMenu(item.children))
: elem('li', text(item))
const toMenu = (all = []) =>
elem('ul', ...all.map(toMenu1))
var categories = [{
text: "engine",
children: [1, 2, 3, {
text: "piston",
children: [4, 5, 6, {
text: "piston",
children: [4, 5, 6]
}]
}]
}, {
text: "tire",
children: [7, 8, 9]
}];
const ul = toMenu(categories)
document.getElementById("menu").appendChild(ul)
li>ul {
display: none;
}
li:hover>ul {
display: block;
}
<div id="menu"></div>
现在回答您的具体问题:我们可以仅使用一个输入项来构建递归菜单吗?
您可以通过以下两种方式之一执行此操作。1)通过抓住你关心的项目 -
const ul = toMenu([ categories[0] ]) // just the first category
// <ul>
// <li>engine<ul>...</ul></li>
// </ul>
或 2) 通过使用Array.prototype.filter
-
const ul = toMenu(categories.filter(c => c.text === "engine"))
// <ul>
// <li>engine<ul>...</ul></li>
// </ul>
奖励:toMenu1
和之间的特殊关系toMenu
称为相互递归。toMenu1
调用toMenu
,调用toMenu1
,调用toMenu
,等等......
推荐阅读
- django - 在 Django Web 应用程序中设置 DEBUG=False 时出错
- https - ESP8266 https 证书连接失败
- python - 如何连接具有 2 个不同维度的 2d 张量
- python - 未解决的导入
- centos - 登录 Piranha CMS Manager 时出现问题
- node.js - 如何将 SQL 转换为 Mongoose 查询 api
- python - 在excel上合并多个工作表
- google-cloud-platform - 是什么导致此 GCP GAE [RESOURCE_EXHAUSTED] 配额错误?
- amazon-web-services - aws - 是否可以在 lambda 函数中使用 Cognito 用户池自定义字段?
- python - 我无法在 python 上加载 json 文件(JSONDecodeError:额外数据)