【问题标题】:Getting only one element of the array and its children仅获取数组的一个元素及其子元素
【发布时间】:2019-05-21 01:05:24
【问题描述】:

我有一个多维数组categories,我正在使用menuToElement 函数循环这个数组。

它获取array 及其子元素的所有元素,并在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>

【问题讨论】:

  • 听起来像 filter() 应该有帮助:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • 请同时显示您的无效代码。
  • 我正在尝试但不起作用的是更改 const ul = menuToElement(categories); to const ul = menuToElement(categories[0]);
  • 您想将界面从 menuToElement(Array) 更改为 menuToElement(Object)?
  • 是的,我想这就是我想要的

标签: javascript html arrays multidimensional-array


【解决方案1】:

首先,我们从一些让我们的生活更轻松的助手开始:elemtext -

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 -

  1. 如果输入item 是一个对象,返回一个LIitem.text 并在item.children 上调用toMenu
  2. 否则(通过归纳)输入item 不是一个对象。在这种情况下,只需返回带有纯文本的LI
const toMenu1 = (item = {}) =>
  Object(item) === item
    ? elem('li', text(`${item.text} \u25BD`), toMenu(item.children)) // 1
    : elem('li', text(item))                                         // 2

我们还没有写toMenu,但在上面我们看到它需要一个项目数组。写这个函数比上一个更容易 -

  1. 返回一个UL,其中每个项目都使用toMenu1进行转换
const toMenu = (all = []) =>
  elem('ul', ...all.map(toMenu1)) // 1

在我们继续之前,展开下面的sn-p,在你自己的浏览器中验证结果-

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;
}
&lt;div id="menu"&gt;&lt;/div&gt;

现在回答您的具体问题:我们可以只使用一个输入项来构建递归菜单吗?

您可以通过以下两种方式之一进行操作。 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>

奖励toMenu1toMenu 之间的特殊关系称为mutual recursiontoMenu1调用toMenu,它调用toMenu1,它调用toMenu,以此类推……

【讨论】:

    【解决方案2】:

    为此,您需要使用

    Array.from()
    

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

    所以它用于转换 DOM 节点(或子节点) 如果您需要更多解释性评论,请提供

    【讨论】:

    • @1-14x0r 这不是评论。这是一个答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多