应用场景
列表中的成员可鼠标拖拽改变顺序
实施步骤
前置引入
import type { DragEndEvent } from '@dnd-kit/core'
import { DndContext } from '@dnd-kit/core'
import {
arrayMove,
/*垂直列表使用verticalListSortingStrategy,
横向列表使用horizontalListSortingStrategy
*/
verticalListSortingStrategy,
SortableContext,
useSortable,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import React from "react"
//这个也是根据列表朝向选择vertical或horizontal
import { restrictToVerticalAxis } from "@dnd-kit/modifiers"
定义列表成员,这里用的ts
//组件外定义
declare interface DraggableTabPaneProps extends React.HTMLAttributes<HTMLLIElement> {
'data-item-key': string
}
const DraggableListNode = ({ children, ...props }: DraggableTabPaneProps) => {
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition } = useSortable({
id: props['data-item-key'],
})
const style: React.CSSProperties = {
...props.style,
transform: CSS.Translate.toString(transform),
transition,
}
return (
<li {...props} ref={setNodeRef} style={style} {...attributes}>
{
React.Children.map(children, child => {
//这里是指定一个拖拽触发的手柄,如果需要整个列表项触发拖拽,就不要这个
if ((child as React.ReactElement<HTMLElement>).props.className.includes('handlemove')) {
return React.cloneElement(child as React.ReactElement, {
...listeners,
ref: setActivatorNodeRef,
})
}
return child
})
}
</li>
)
}
渲染列表
//组件内定义
const data=[
{key:1,content:'列表项1'},
{key:2,content:'列表项2'}]
const [items,setItems]=useState(data)
//组件输出部分
<ul>
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={handleDragEnd}>
<SortableContext items={items.map((i) => i.key)} strategy={verticalListSortingStrategy}>
{//上一步声明的DraggableListNode取代了原生的li标签
items.map(item=>(
<DraggableListNode className="listitem" key={item.key} data-item-key={item.key}>
<span className="handlemove">自定义拖拽手柄</span>
{item.content}
</DraggableListNode>
))
}
</SortableContext>
</DndContext>
</ul>
处理拖拽结束事件,改变列表项的顺序
//组件内定义
function handleDragEnd({ active, over }: DragEndEvent) {
if (active.id !== over?.id) {
const activeIndex = items.findIndex((i) => i.key === active.id)
const overIndex = items.findIndex((i) => i.key === over?.id)
const newlist= arrayMove(items, activeIndex, overIndex)
setItems(newlist)
}
}
以上。