react经验15:拖拽排序组件dnd-kit的使用经验

发布于:2024-05-12 ⋅ 阅读:(224) ⋅ 点赞:(0)

应用场景

列表中的成员可鼠标拖拽改变顺序

实施步骤

前置引入

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)

   }
}

以上。


网站公告

今日签到

点亮在社区的每一天
去签到