DevGang
Авторизоваться

Любопытный случай перетаскивания

Перетаскивание может выглядеть как простое взаимодействие с пользователем, при котором вы берете элемент и помещаете его в другое место, аналогично организации элементов на доске Trello или в любом интерфейсе в стиле Kanban, где карточки или информацию можно легко переставлять с помощью щелчка и перетаскивания.

Однако весь этот процесс скрывает за собой много сложностей. Начнем с перемещения данных между разными частями и получения правильной позиции размещения. Эта проблема усложняется, когда у вас есть вложенный слой элементов, которые могут перемещаться по нескольким уровням.

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

  • response-beautiful-dnd выделяется как наиболее часто используемый, он предоставляет чистый и высокоуровневый API с большим количеством абстракции. Он был разработан Atlassian.
  • React-DND довольно мощный, но немного сложный и требует некоторого привыкания.
  • dnd-kit — один из новейших, современный, легкий и производительный.

Проблема

Мы в epilot широко полагались на React-beautiful-dnd и в различных частях нашего приложения.

Тем не менее, в определенных контекстах мы столкнулись с некоторыми препятствиями при попытке реализовать некоторые сложные сценарии, в которых не удалось точно предсказать место падения элемента. Вот один из примеров.

Мы разработали несколько хаков для конкретных крайних случаев, но они не смогли решить все проблемы. Из-за этих крайних случаев код для перемещения данных элемента на основе позиции перетаскивания превратился в код спагетти. Прекращение обслуживания и поддержки response-beautiful-dnd также не способствовало продолжению его использования.

Решение

Наконец, мы решили изучить альтернативные библиотеки, которые могли бы решить наши проблемы с помощью более явного, интуитивно понятного и простого API. Оценив несколько вариантов, мы остановились на dnd-kit, поскольку он предоставляет явный и простой API. Дополнительным преимуществом было то, что он также предоставляет API-интерфейс перехватчиков, который отсутствует в некоторых старых библиотеках.

Ключевые преимущества dnd-kit включают в себя:

  • Нулевые зависимости
  • Оптимизированная производительность
  • Доступность
  • Поддержка нескольких методов ввода

Покажи мне код

Вот коды для простого перетаскивания обеих библиотек.

// react-beautiful-dnd

export const DragDrop = ({ initialData }) => {
  const [items, setItems] = useState(initialData);
  const onDragEnd = () => { /** moving data **/ };

  return (
    <DragDropContext onDragEnd={onDragEnd}>
      <Droppable droppableId="droppable">
        {(provided) => (
          <ul {...provided.droppableProps} ref={provided.innerRef}>
            {items.map((item, index) => (
              <DraggableItem item={item} key={item.id} index={index} />
            ))}
            {provided.placeholder}
          </ul>
        )}
      </Droppable>
    </DragDropContext>
  );
};

const DraggableItem = ({ item, index }) => (
  <Draggable draggableId={item.id} index={index}>
    {(provided) => (
      <li
        {...provided.draggableProps}
        {...provided.dragHandleProps}
        ref={provided.innerRef}
      >
        {item.content}
      </li>
    )}
  </Draggable>
);
// dnd-kit

export const DndKit = ({ initialData }) => {
  const [items, setItems] = useState(initialData);
  const onDragEnd = () => { /** moving data **/ };

  const sensors = useSensors(useSensor(PointerSensor));

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <SortableContext items={items} strategy={verticalListSortingStrategy}>
        <ul>
          {items.map((item) => (
            <DraggableItem item={item} key={item.id} />
          ))}
        </ul>
      </SortableContext>
    </DndContext>
  );
};

const DraggableItem = ({ item }) => {
  const {
    attributes,
    isDragging,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({
    id: item.id,
  });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    cursor: isDragging ? "grabbing" : "grab",
  };

  return (
    <li
      {...attributes}
      {...listeners}
      key={item.id}
      data-dnd-id={item.id}
      data-dnd-type="item"
      ref={setNodeRef}
      style={style}
    >
      {item.content}
    </li>
  );
};

Полный код можно найти в этой Codesandbox.

Среди этих примеров кода, имеющих одинаковую функциональность, можно заметить, что dnd-kit имеет более высокую сложность, но также и более комплексный. Для решения этой проблемы он использует Sortable, поскольку это один из вариантов использования, который он решает. Это соответствует нашей цели — решать более сложные сценарии с помощью вложенного перетаскивания и возможности перетаскивания между разными уровнями.

Ключевые преимущества dnd-kit, которые пригодились, включают в себя:

  • Пользовательский заполнитель. Это один из наиболее желательных вариантов использования. Достичь этого в React-beautiful-dnd может быть непросто, так как у него будут ограниченные возможности и много JavaScript для достижения удовлетворительного состояния. В нашем сценарии мы хотели показать сжатую версию элемента с дочерними элементами во время перетаскивания, поэтому мы использовали DragOverlay с порталом React.
  • Стратегии обнаружения столкновений. Предлагает различные стратегии, специфичные для разных вариантов использования, обеспечивая контроль над переключением элементов внутри дерева. Вы даже можете разработать свою собственную стратегию, отвечающую вашим требованиям.
  • Стратегии сортировки. Аналогично, он предлагает различные стратегии сортировки, позволяющие сортировать вертикальные списки, горизонтальные списки или сетки.

Ознакомьтесь с этой упрощенной версией нашего варианта использования на Epilot с функцией перетаскивания вложенных элементов в этой песочнице Codes.

Заключение

В конечном счете, выбор между ними зависит от ваших конкретных требований, предпочтений и желаемого уровня настройки. Если вы предпочитаете более простой и самоуверенный подход, лучшим выбором будет action-beautiful-dnd. Если вам нужны дополнительные возможности настройки и контроля, dnd-kit может лучше соответствовать вашим потребностям.

Источник:

#JavaScript #React
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться