0


react 基于 dnd-kit 封装的拖拽排序组件

dnd-kit使用方法

npm install @dnd-kit/core
npm install @dnd-kit/sortable
  • 简单使用

建议直接看官网,已经描述得很详细了:https://docs.dndkit.com/presets/sortable

封装成组件使用

效果展示

type dataType ={id: string
  title: string
}exportdefault()=>{const[list, setList]= useState<dataType[]>([])useEffect(()=>{getData()},[])constgetData=async()=>{setTimeout(()=>{const data =newArray(10).fill('标题-').map((s,i)=>({id:'id-'+ i,title: s + i}))setList(data)},200);}constonDragEnd=(list: dataType[],ids: string[])=>{setList(list)}return(<div ><SortListDndKit list={list} onDragEnd={onDragEnd}>{list.map((item)=>(<SortItemDndKit key={item.id} id={item.id}><div><h4>{item.title}</h4></div></SortItemDndKit>))}</SortListDndKit></div>)}

注意事项

  1. 如果传入的是一个函数式组件,需要用一个html元素包裹住
<SortListDndKitlist={list}onDragEnd={onDragEnd}>
{list.map((item) => (
  <SortItemDndKit>
    {/* 这里需要用html元素包裹一下 */}
    <div><Texttitle='测试组件'/></div></SortItemDndKit> 
))}
</SortListDndKit>
  1. 这里的排序默认是读取 list 中的 id 作为 key 值的,如果 key 值是其他,可以指定 list 中传入的 idKey
{/* newId:list中的id名称 */}
<SortListDndKitidKey="newId"list={list}onDragEnd={onDragEnd}></SortListDndKit>
  1. 如果内部的元素绑定了鼠标点击之类的事件,需要先阻止事件冒泡 onMouseDown={e => e.stopPropagation()}
<SortListDndKitlist={list}onDragEnd={onDragEnd}>
{list.map((item) => (
  <SortItemDndKit>
    {/* 这里需要用html元素包裹一下 */}
    <div><h4>这里有很多内容</h4>
      {/* 这里需要阻止鼠标点击事件的冒泡 */}
      <button onMouseDown={e => e.stopPropagation()} onClick={()=>console.log('点击了')} >点击</button></div></SortItemDndKit> 
))}
</SortListDndKit>

组件源码

import React,{ ReactNode }from'react';import{
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
  DragEndEvent,
  MouseSensor,}from'@dnd-kit/core';import{
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  useSortable,}from'@dnd-kit/sortable';import{CSS}from'@dnd-kit/utilities';

type PropsType ={/** 需要传递的列表 */list: any[];/** list的key值,默认是id */
  idKey?: string;children: ReactNode;/** 拖拽结束的回调 */onDragEnd:(arr: any[],ids: string[])=>void;};/** 参考官网:https://docs.dndkit.com/presets/sortable *//** 
 * 列表排序
 */exportconst SortListDndKit =({
  list =[],
  idKey ='id',
  children,
  onDragEnd,}: PropsType)=>{// 指定传感器,默认是全部const sensors =useSensors(// useSensor(PointerSensor),useSensor(MouseSensor),useSensor(KeyboardSensor,{coordinateGetter: sortableKeyboardCoordinates,}),);// 拖拽结束consthandleDragEnd=(event: DragEndEvent)=>{const{ active, over }= event;if(active.id !== over.id){const oldIndex = list.findIndex((item)=> item[idKey]=== active.id);const newIndex = list.findIndex((item)=> item[idKey]=== over.id);constids: string[]= list.map((item)=> item[idKey]);[ids[newIndex], ids[oldIndex]]=[ids[oldIndex], ids[newIndex]];const _val =arrayMove(list, oldIndex, newIndex);onDragEnd(_val, ids);}};return(<DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}><SortableContext items={list.map((item)=> item[idKey])}>{children}</SortableContext></DndContext>);};

type SortItemType ={id: string;children: ReactNode;};/**
 * 列表排序的子项
 * - 函数式组件作为children,需要用html元素包裹住
 * - 例:
 * - \<SortItemDndKit>
 * -   \<div>\<Text title='测试组件' />\</div>
 * - \</SortItemDndKit> 
 */exportconstSortItemDndKit=({ id, children }: SortItemType)=>{const{ attributes, listeners, setNodeRef, transform, transition }=useSortable({ id });const style ={transform:CSS.Transform.toString(transform),
    transition,};const newChild = React.Children.map(children,(child)=>{if(!React.isValidElement(child)){returnnull;}const childProps ={...child.props,ref: setNodeRef,
      style,...attributes,...listeners,};return React.cloneElement(child, childProps);});return<>{newChild}</>;};

本文转载自: https://blog.csdn.net/weixin_52014110/article/details/127758204
版权归原作者 滑动变滚动的蜗牛 所有, 如有侵权,请联系我们删除。

“react 基于 dnd-kit 封装的拖拽排序组件”的评论:

还没有评论