标签的拖拽排序

2023-8-7 1,158 8/7

基于react-dnd 库实现标签的拖拽排序的需求。 其实理解后还是挺好做的。

我觉得核心处理的点在于如何使标签组件既可以拖动又可以接受拖动

核心处理的点在于

 drop(drag(ref))

drpo与drag通过 useDrag和 useDrop去拿到。

 

我的标签组件

type DragTagProps = {
  id: string | number;
  index: string | number;
  type: string;
  selected:Tag | undefined,
  canAdd: boolean,
  tag: Tag
  onDragEnd: (dragIndex: string | number, hoverIndex: string | number, type: string) => void;
  select: (tag:Tag)=>void,
  clone: (tag:Tag)=>void,
  remove: (tag:Tag)=>void,
}
const DragTag: React.FC<DragTagProps> = ({
  id = '',
  index = '',
  onDragEnd,
  type,
  remove,
  select,
  clone,
  canAdd,
  selected,
  tag
}) => {
  const ref = useRef(null)
  const [, drop] = useDrop({
    accept: 'Drag',
    hover: (item: any) => {
      if (!ref.current) return
      const dragIndex = item.index
      const hoverIndex = index
      if (dragIndex === hoverIndex) return
      onDragEnd(dragIndex, hoverIndex, type)
      item.index = hoverIndex
    },
    collect: monitor => ({
      isOver: monitor.isOver({ shallow: true }),
      canDrop: monitor.canDrop(),
    }),
  })

  const [{ isDragging }, drag] = useDrag({
    // @ts-ignore
    type: 'Drag',
    item: {
      type: 'Drag',
      id,
      index,
    },
    collect: (monitor: any) => ({
      isDragging: monitor.isDragging(),
    }),
  })

  drop(drag(ref))

  return (
    <div
      key={tag.id}
      className={classNames(styles.tag, { [styles.selected]: selected?.id === tag.id })}
      onClick={() => select(tag)}
      ref={ref}
      style={{ opacity: isDragging ? 0.5 : 1 }}
    >
      {tag.name}
      <div onClick={e => e.stopPropagation()}>
        <Dropdown
          menu={{
            items: [
              // @ts-ignore
              canAdd && { key: 2, label: <span onClick={() => clone(tag)}>复制</span> },
              { key: 1, label: <span onClick={() => remove(tag)}>删除</span> },
            ]
          }}
        >
          <i className="iconfont">&#xe6c3;</i>
        </Dropdown>
      </div>
    </div>
  )
}

 

在父组件中的使用片段,切实自己的具体需求使用

实现的拖动的方法,这里做一些浅拷贝,不然state不会更新,

  const onDragEnd = (dragIndex: any, hoverIndex: any, type?: string) => {
    //依次往后挪
    const [draggedItem] = value.splice?.(dragIndex, 1);
    value.splice?.(hoverIndex, 0, draggedItem);
    onChange?.([...value])
  };

 

render片段

<DndProvider backend={HTML5Backend}>
          {value.map((tag, index) => (
            <DragTag
              tag={tag}
              onDragEnd={onDragEnd}
              clone={clone}
              selected={selected}
              select={select}
              id={tag?.id}
              type={' '}
              index={index}
              canAdd={canAdd}
              remove={remove}
            />
          ))}
        </DndProvider>

 

因为还需要往后端加sort,标签对应的顺序,其实我们拖动标签后,dataSource 也就是数据源 数组也会发生改变,在保存那里,sort就等于遍历dataSource的index加1.

- THE END -
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论