Разработка канбан-доски с использованием react-dnd


Канбан-доска

Drag-and-Drop — одна из замечательных функций HTML5. Раньше мы полагались на события мыши javascript для достижения перетаскивания. Но HTML5 упростил рабочий процесс. Но заставить работать перетаскивание в среде React сложно. Потому что может возникнуть конфликт между прямым манипулированием DOM и виртуальным DOM, поддерживаемым React. Здесь на сцену выходит react-dnd — простая и прямая библиотека, которая помогает нам работать с перетаскиванием HTML5 в среде реагирования.

Код, используемый в этом руководстве, доступен по адресу

Также вы можете проверить это в приведенных ниже кодах и коробке.

Для начала нам нужно добавить две библиотеки.

$ npm install react-dnd react-dnd-html5-backend

$ npm install react-dnd react-dnd-html5-backend
  1. реагировать-днд обеспечивает всю логику и
  2. реагировать-dnd-html5-бэкэнд привязывает логику к API html5.

Для завершения рабочего процесса необходимо обработать три узла dom или компонент jsx.

  1. перетаскиваемые объекты : В нашем примере с доской Канбан каждый элемент задачи является перетаскиваемым объектом. Предметы, которые мы можем перетаскивать.
  2. сбрасываемые контейнеры: Каждый столбец на канбан-доске представляет собой переносной контейнер. Мы можем перетащить любой элемент задачи и поместить их в этот контейнер.
  3. Перетащите контекст: Оболочка, в которой заключены все перетаскиваемые объекты и выпадающие контейнеры. Это необходимо для установки границы и инициализации сцены. Можно иметь несколько перетаскиваний, имея несколько неперекрывающихся контекстов.

Все эти три функции реализованы как компоненты более высокого порядка, охватывающие компоненты представления.

import { DragDropContext, DropTarget, DragSource } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";

Плата представлена ​​нижеследующей структурой. Это может показаться немного сложным, но позвольте мне выделить некоторые моменты.

<section>
{channels.map(channel => (
  <KanbanColumn status={channel}>
    <div>
      <div>{labelsMap[channel]}</div>
      <div>
      {tasks.filter(item => item.status === channel)
        .map(item => (
          <KanbanItem id={item._id} onDrop={this.update}>
            <div style={classes.item}>{item.title}</div>
          </KanbanItem>
      ))}
      </div>
    </div>
  </KanbanColumn>
  ))}
</section>

У нас есть двухуровневый вложенный цикл dom с использованием Array.map, первый отображает столбцы доски канбан, а второй отображает элементы задачи. Также обратите внимание, что есть два компонента, которые я объясню позже. Но перед этим корневой компонент канбана должен быть связан с react-dnd, как показано ниже.

export default DragDropContext(HTML5Backend)(Kanban);

Выпадающий контейнер

Компонент колонки канбан-доски представлен ниже.

const boxTarget = {
  drop(props) {
    return { name: props.status };
  }
};

class KanbanColumn extends React.Component {
  render() {
    return this.props.connectDropTarget(
      <div>{this.props.children}</div>
    );
  }
}

KanbanColumn = DropTarget("kanbanItem", boxTarget, 
  (connect, monitor) => ({
    connectDropTarget: connect.dropTarget(),
    isOver: monitor.isOver(),
    canDrop: monitor.canDrop()
  }))(KanbanColumn);

коробкаЦель объект имеет коллекцию событий, которые нас интересуют. Здесь нас интересует только событие ‘drop’. Как только происходит событие удаления, мы сообщаем, что элемент задачи удаляется в конкретном столбце, который доступен в ‘props.status’.

Компонент KanbanColumn не содержит пользовательского интерфейса, вместо этого он передается как дочерний элемент.

Перетаскиваемый элемент

const boxSource = {
  beginDrag(props) {
    return {
      name: props.id
    };
  },
  endDrag(props, monitor) {
    const item = monitor.getItem();
    const dropResult = monitor.getDropResult();
    if (dropResult) {
      props.onDrop(monitor.getItem().name, dropResult.name);
    }
  }
};

class KanbanItem extends React.Component {
  render() {
    return this.props.connectDragSource(
      <div>{this.props.children}</div>
    );
  }
}

KanbanItem = DragSource("kanbanItem", boxSource, 
  (connect, monitor) => ({
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  }))(KanbanItem);

Он похож на предыдущий компонент, но имеет кое-что дополнительное.

boxИсточник объект представляет собой интересующую нас коллекцию слушателей. На самом деле нас интересуют два события. Когда начинается перетаскивание, мы собираем идентификатор перетаскиваемого элемента. И когда сброс завершается, мы собираем имя столбца, на который он сбрасывается.

Всякий раз, когда происходит перетаскивание, нас интересуют две информации. Что тянут? А где предмет выпадает? Когда у нас есть оба, мы передаем их родительскому компоненту ( реквизит.onDrop )

И ответственность за изменение состояния лежит на родителе. В нашем примере мы используем библиотеку immutability-helper. Но есть много способов справиться с этим.

И последнее замечание. Это нормально работает только на компьютерах, а не на сенсорных экранах, потому что перетаскивание html5 изначально недоступно на сенсорных устройствах. Но есть и другие альтернативы бэкенду, которые отлично сочетаются с react-dnd.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *