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>)}
注意事项
- 如果传入的是一个函数式组件,需要用一个html元素包裹住
<SortListDndKitlist={list}onDragEnd={onDragEnd}>
{list.map((item) => (
<SortItemDndKit>
{/* 这里需要用html元素包裹一下 */}
<div><Texttitle='测试组件'/></div></SortItemDndKit>
))}
</SortListDndKit>
- 这里的排序默认是读取
list
中的id
作为key
值的,如果key
值是其他,可以指定list
中传入的idKey
{/* newId:list中的id名称 */}
<SortListDndKitidKey="newId"list={list}onDragEnd={onDragEnd}></SortListDndKit>
- 如果内部的元素绑定了鼠标点击之类的事件,需要先阻止事件冒泡
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
版权归原作者 滑动变滚动的蜗牛 所有, 如有侵权,请联系我们删除。
版权归原作者 滑动变滚动的蜗牛 所有, 如有侵权,请联系我们删除。