【拖拽排序插件】dnd-kit

插件选择

react常用的拖拽排序插件,一般会推荐这几个:react-beautiful-dnd、react-dnd、dnd-kit、react-sortable-hoc,怎么选择呢react-beautiful-dnd插件可以去git上看看作者说不再维护了,并且npm仓库里面也是没有的,你去下载会报错,就不用了,react-dnd插件比较大,实现复杂的拖拽场景,就暂时不用它,剩下两个随便挑一个把,就以dnd-kit为例子。

1.安装

我们需要安装下面几个相关插件:@dnd-kit/core、@dnd-kit/sortable、@dnd-kit/utilities

他们一次的功能在于拖动,排序,以及样式,下面我们从代码中可以看出来。

pnpm install @dnd-kit/core

2.使用场景和代码

一个简单的场景,一组div的列,可以拖动排序,下面是写成的组件代码:

1)组件代码

import { injectIntl } from "react-intl";
import { DndContext, closestCenter } from '@dnd-kit/core';
import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { useState } from "react";
import { CSS } from '@dnd-kit/utilities';
import './my-dnd.less'

interface props_type {
    items: any,
    onDragEnd: any,
    renderItem: any,
    prefix: any,
    className: string
}

const DraggableRow = ({ id, render, item, prefix, className, activeId }: any) => {
    const { attributes, listeners, transform, setNodeRef, transition } = useSortable({ id });
    const isDragging = id === activeId;

    const style = {
      transform: CSS.Transform.toString(transform),
      transition,
      background: isDragging ? 'linear-gradient(rgba(0, 140, 214, 0.1), rgba(0, 110, 255, 0.1)), #ffffff' : ''
    };
  
    return (
      <div ref={setNodeRef} style={style} className={`${className} dnd-item`}>
        <div {...attributes} {...listeners} className="drag-icon">
          {prefix}
        </div>
        {render(item)}
      </div>
    );
};


const MyDnd: React.FC<any> = (props: props_type) => {
    const { items, onDragEnd, renderItem, prefix, className } = props;
    const [currentItems, setCurrentItems] = useState(items);
    const [activeId, setActiveId] = useState(null);

  const handleDragEnd = (event: any) => {
    const { active, over } = event;

    if (active.id !== over.id) {
      const oldIndex = currentItems.findIndex((item: any) => item.id === active.id);
      const newIndex = currentItems.findIndex((item: any) => item.id === over.id);

      const newItems = arrayMove(currentItems, oldIndex, newIndex);
      setCurrentItems(newItems);
      onDragEnd && onDragEnd(newItems);
    }
    setActiveId(null);
  };

  return (
    <DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd} onDragStart={(e: any) => setActiveId(e.active.id)}>
      <SortableContext items={currentItems.map((item: any) => item.id)} strategy={verticalListSortingStrategy}>
        {currentItems.map((item: any) => (
          <DraggableRow
            key={item.id}
            id={item.id}
            item={item}
            render={renderItem}
            prefix={prefix}
            className={className}
            activeId={activeId}
          />
        ))}
      </SortableContext>
    </DndContext>
  );
}

export default injectIntl(MyDnd) as any;

 

2)如何使用

import MyDnd from "./my-dnd";

<MyDnd
 items={list} 
 onDragEnd={(newItems: any) => set_list(newItems)}
 renderItem={renderRow}
 prefix={icon}
 className={'file-item'}
/>

3.代码分析

1)MyDnd传参

        先从使用的地方看,items是需要传入到SortableContext中进行排序的源数据,onDragEnd是触发完成排序后的回调函数,返回的是新的数据,renderItem是你自己定义的页面的样式每一行的,perfix是自定义每一行前面的icon,这里我是穿了个按钮进去,并把拖拽的动作挂载(listeners,随后会介绍)在这个按钮上的。

2)MyDnd代码

然后就进入组件的代码:DndContext :将整个应用包裹在DndContext 中,并设置 collisionDetectionclosestCenter(检测最近的元素碰撞),SortableContextSortableContext 包裹所有可排序项,设置 strategyverticalListSortingStrategy(垂直列表的排序策略)。中间就是你要加载的自己的内容啦,就是renderItemuseSortable 提供了处理单个元素拖拽的基本接口。

3)样式

@dnd-kit/utilities主要提供了拖动时触发的样式效果。

大概就是这样,具体的API可以再具体查询。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值