记录拖动排序

最近项目中要做一个拖动排序功能,首先想到的是之前项目中用过的antd自带的tree和table的拖动排序,但是只能在对应的组建里使用。这里用的是自定义组件,随意拖动排序,所以记录一下实现流程

  1. react-dnd antd组件的拖动排序都是用的这个库,使用比较灵活,但是要配置的东西比较多,需求复杂时使用这个库;
    class BodyRow extends React.Component {
      render() {
        const { isOver, connectDragSource, connectDropTarget, moveRow, ...restProps } = this.props;
        const style = { ...restProps.style, cursor: 'move' };
    
        let { className } = restProps;
        if (isOver) {
          if (restProps.index > dragingIndex) {
            className += ' drop-over-downward';
          }
          if (restProps.index < dragingIndex) {
            className += ' drop-over-upward';
          }
        }
        return connectDragSource(
          connectDropTarget(<tr {...restProps} className={className} style={style} />),
        );
      }
    }
    const rowSource = {
      beginDrag(props) {
        dragingIndex = props.index;
        return {
          index: props.index,
        };
      },
    };
    const rowTarget = {
      drop(props, monitor) {
        const dragIndex = monitor.getItem().index;
        const hoverIndex = props.index;
        // Don't replace items with themselves
        if (dragIndex === hoverIndex) {
          return;
        }
        // Time to actually perform the action
        props.moveRow(dragIndex, hoverIndex);
        // Note: we're mutating the monitor item here!
        // Generally it's better to avoid mutations,
        // but it's good here for the sake of performance
        // to avoid expensive index searches.
        monitor.getItem().index = hoverIndex;
      },
    };
    const DragableBodyRow = DropTarget('row', rowTarget, (connect, monitor) => ({
      connectDropTarget: connect.dropTarget(),
      isOver: monitor.isOver(),
    }))(
      DragSource('row', rowSource, connect => ({
        connectDragSource: connect.dragSource(),
      }))(BodyRow),
    );
    
    <DndProvider backend={HTML5Backend}>
      <Table
        columns={columns}
        dataSource={this.state.data}
        components={this.components}
        onRow={(record, index) => ({
          index,
          moveRow: this.moveRow,
        })}
      />
    </DndProvider>
    
  2. react-beautiful-dnd 在项目中看到引用了这个库,使用起来也不算复杂,就试着用了这个库,不过只支持水平或垂直拖动,一行或者一列元素时可以使用,可惜这个需求时两行多列元素,也没办法用;
    <DragDropContext onDragEnd={this.onDragEnd}>
      <Droppable droppableId='phone-droppable'>
        {droppableProvided => (
          <div ref={droppableProvided.innerRef} {...droppableProvided.droppableProps}>
            {this.state.phoneImages.map((image, index) => (
              <Draggable key={image||'upload'} draggableId={image||'upload'} index={index}>
                {(provided, snapshot) => (
                  <div
                    ref={provided.innerRef}
                    {...provided.draggableProps}
                    {...provided.dragHandleProps}
                    style={{
                      ...provided.draggableProps.style,
                      opacity: snapshot.isDragging ? 0.8 : 1,
                      display: 'inline-block'
                    }}
                  >
                    <img src={img}/>
                  </div>
                )}
              </Draggable>
            ))}
            {droppableProvided.placeholder}
          </div>
        )}
      </Droppable>
    </DragDropContext>
    
  3. react-sortable-hoc 最后在网上搜索的时候,又看到这个库,使用起来比较简单,使用SortableList包裹要拖拽元素的容器,SortableElement包裹要拖拽的子元素,设置容器拖拽方向axis={'xy'}即可使grid布局的多个元素支持水平和竖直方向拖动排序;
    const SortableItem = SortableElement(({children}) => (
      <div>{children}</div>
    ));
    const SortableList = SortableContainer(({children}) => {
      return (
        <div style={{display: 'grid', gridTemplateRows: '117px 117px', gridTemplateColumns: '120px 120px 120px 120px'}}>
          {children}
        </div>
      );
    });
    
    <SortableList onSortEnd={this.onPadSortEnd} helperClass={Styles.sortableHelper} axis={'xy'}>
      {this.state.padImages.map((image, index) => (
        <SortableItem key={`pad-item-${index}`} index={index} className={Styles.sortableItem}>
          <img src={img}/>
        </SortableItem>
      ))}
    </SortableList>
    

好久没更新博客了,最近工作比较忙,差不多每天都要加班,中间有经历搬家,没时间坐下来总结学到的东西。工作的时候因为这块花费了一些时间,想到可能别人也会遇到类似问题,所以就记录下来了

热门相关:总裁别再玩了   半仙   变身蜘蛛侠   重生野性时代   富贵不能吟