mcc-nested-list Tailwind Templates

Mcc Nested List

react, scss/sass, tailwind

Задание

Реализовать приложение с древовидной структурой элементов с возможностью:

  • Добавлять новый элемент в конец списка или в произвольную позицию (следом за выбранным элементом)
  • Удалить элемент (вместе со всеми вложенными элементами)
  • Редактировать текст внутри элемента
  • Отменить редактирование (и вернуть в элемент исходный текст)
  • Сбросить список до начального состояния

При этом необходимо реализовать возможность работы приложения с тремя разными вариантами структуры исходных данных.

Требования:

  • React JS
  • Адаптивная вёрстка
  • Разделение логики обработки данных и отрисовки

Реализация

Краткий список оставшихся задач:

  • Реализовать третий вариант
  • Вынести отрисовку компонентов отдельно (так, чтобы все три реализации использовали одни и те же jsx), логику отдельно
  • Полностью отделить отрисовку компонентов от логики формирования данных - убрать из CRUD*.js файлов.
  • Оптимизировать код, вынести повторяющиеся участки в отдельные функции/файлы
  • Заменить все key (реализовано не идеальное решение, но т.к. у объектов нет уникальных id, другого пока нет)
  • Для первой реализации изменить логику поднятия элемента. Если сверху уже родитель - то не поднимать (ожидается, что пользователь сначала должен перенести этот элемент на уровень выше)
  • Для первой реализации изменить логику "влево". Если это не последний элемент на своём уровне - то он должен перемещаться в родительский элемент в самую последнюю позицию.
  • Реализовать возможность добавления элемента списка в указанную позицию для третьей реализации
  • Переписать код на TypeScript (написал сначала на JS, т.к. это быстрее)

Элементы управления

Интерфейс приложения интуитивно понятный. У каждого элемента справа есть кнопки для перемещения и удаления. Для редактирования достаточно нажать на текст элемента. Для сохранения изменений нужно нажать Enter.

Варианты реализаций исходных данных:

  1. Массив элементов без вложенности, каждый из элементов хранит значение своего уровня вложенности.

Пример:

[{
    text: 'Text 1',
    level: 1,
},
{
    text: 'Text 1-1',
    level: 2,
},
{
    text: 'Text 1-1-1',
    level: 3,
},
{
    text: 'Text 1-1-2',
    level: 3,
},
{
    text: 'Text 1-2',
    level: 2,
},
{
    text: 'Text 2',
    level: 1,
}]
  1. Многомерная структура данных из вложенных массивов, которая повторяет структуру элементов списка при их отображении.

Пример:

[{
    name: 'Text 1',
    child: [
        {
            text: 'Text 1-1',
            child: [
                {
                    text: 'Text 1-1-1',
                    child: null,
                },
                {
                    text: 'Text 1-1-2',
                    child: null,
                },
            ],
        },
        {
            text: 'Text 1-2',
            child: null,
        },
    ],
},
{
    text: 'Text 2',
    child: null,
}]
  1. Одномерная структура данных с полями-указателями на родительский элемент.

Пример:

[{
    id: 1,
    text: 'Text 1',
    parent: null,
},
{
    id: 2,
    text: 'Text 1-1',
    parent: 1,
},
{
    id: 6,
    text: 'Text 2',
    parent: null,
},
{
    id: 3,
    text: 'Text 1-1-1',
    parent: 2,
},
{
    id: 5,
    text: 'Text 1-2',
    parent: 1,
},
{
    id: 4,
    text: 'Text 1-1-2',
    parent: 2,
}]

Сравнение трёх вариантов


Первый способ Второй способ Третий способ
Преимущества Максимально простая реализация, высокая скорость работы * Отриосованные DOM элементы действительно вложены друг в друга
* Малый размер JSON файла
* Наглядное представление вложенности данных при просмотре JSON
* При добавлении нового элемента в любое место в списке, достаточно добавить новый элемент в конец массива и указать id родителя, без необходимости менять местами уже существующие элементы массива
* Для перемещения элемента в массиве достаточно изменить одну переменную (id родителя), он переместится сразу вместе с вложенными элементами
Недостатки Для реализации перемещения элементов вместе с вложенными - необходимо выполнить проход по массиву и найти все вложенные элементы При каждом изменении положения элемента, требуется выполнять рекурсивный поиск. Производительность сравнима с первым вариантом, но такой код сложнее поддерживать. * Данные сложно прочитать из JSON
* JSON файл с данными занимает сравнительно больше места
Читаемость данных в сыром (JSON) виде Все элементы хранятся на одном уровне:
- к наглядности вложенности
+ не требуется широкий экран/горизонтальный скролл
Элементы вложены так же, как и при выводе списка.
+ удобно оценить уровень вложнности
- удобно до тех пор, пока вложенность не большая
Самый неудобный вариант среди прочих, т.к. данные могут быть расположены не в порядке вывода на экран.
Простота реализации отрисовки Вывод элементов максимально простой: проход по одномерному массиву, добавление стилей для изменения отступов Рекурсивная функция для отрисовки элементов - несколько сложнее первой реализации Здесь есть несколько вариантов для отрисовки. Самый простой: несколько проходов по массиву с данными, поиск "детей" для каждого элемента
Простота удаления элемента Максимально просто. Зная индекс элемента в массиве - можно напрямую его удалить, без перебора элементов массива Сложный рекурсивный поиск элемента. Даже если бы мы хранили id элементов, от рекурсивного поиска не избавиться (если не использовать дополнительный массив для словаря) Простой поиск id в одномерном массиве
Объём, необходимый для хранения данных, помимо текста элемента (размер JSON файла) 1 числовое значение (номер уровня вложенности) Указатель на вложенный массив (название переменной и пара скобок) 2 числовых значения: id собственный и id родителя

Top categories

Loading Svelte Themes