Задать вопрос

Как можно сформировать дерево категорий в javascript?

Каким образом можно создать древовидный вывод в html подкатегорий?
формат, который мне приходит, обычный для таких ситуаций:
{id: 1, name: "Категория 1", parent_id: 0}
{id: 2, name: "Категория 2", parent_id: 0}
{id: 3, name: "Категория 3", parent_id: 1}

Я так понимаю лучше всего это сделать через рекурсии?
  • Вопрос задан
  • 738 просмотров
Подписаться 1 Простой 1 комментарий
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
Сперва превращаем плоский массив во вложенный:

function createTreeData(arr, idKey, parentKey) {
  const tree = Object.fromEntries(arr.map(n => [ n[idKey], { ...n, children: [] } ]));
  return Object.values(tree).filter(n => !tree[n[parentKey]]?.children.push(n));
}


const treeData = createTreeData(data, 'id', 'parent_id');

Затем можно собрать разметку дерева:

const createTreeHTML = data =>
  Array.isArray(data) && data.length
    ? `<ul>${data.map(n => `
         <li>
           ${n.name}
           ${createTreeHTML(n.children)}
         </li>`).join('')}
       </ul>`
    : '';


document.body.insertAdjacentHTML('beforeend', createTreeHTML(treeData));

Или, создавать элементы напрямую:

const createTreeElement = data =>
  data instanceof Array && data.length
    ? data.reduce((ul, n) => (
        ul.append(document.createElement('li')),
        ul.lastChild.append(n.name, createTreeElement(n.children)),
        ul
      ), document.createElement('ul'))
    : '';


document.body.append(createTreeElement(treeData));

ИЛИ

Без создания промежуточного вложенного массива:

function createTreeElement(arr, idKey, parentKey) {
  const tree = arr.reduce((acc, { [parentKey]: n }) => (
    acc[n] = acc[n] ?? document.createElement('ul'),
    acc
  ), {});

  arr.forEach(n => (
    tree[n[parentKey]].append(document.createElement('li')),
    tree[n[parentKey]].lastChild.append(n.name, tree[n[idKey]] ?? '')
  ));

  return Object.values(tree).reduce((ul, n) => (
    n.parentNode || ul.append(...n.children),
    ul
  ), document.createElement('ul'));
  // или, если не надо объединять в общий список элементы, у которых разные корневые parent_id
  // return Object.values(tree).filter(n => !n.parentNode);
}


document.body.append(createTreeElement(data, 'id', 'parent_id'));
Ответ написан
Комментировать
evgen3
@evgen3
Фронтэнды
можно без рекурсии, в принципе: https://jsfiddle.net/y1ehn4v6/
просто через поиск по DOM
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы