dnd-kit使用方法
-
官網(wǎng)地址 https://docs.dndkit.com/introduction/installation
-
安裝依賴文章來源:http://www.zghlxwxcb.cn/news/detail-598712.html
npm install @dnd-kit/core
npm install @dnd-kit/sortable
- 簡(jiǎn)單使用
建議直接看官網(wǎng),已經(jīng)描述得很詳細(xì)了:https://docs.dndkit.com/presets/sortable文章來源地址http://www.zghlxwxcb.cn/news/detail-598712.html
封裝成組件使用
效果展示

type dataType = {
id: string
title: string
}
export default () => {
const [list, setList] = useState<dataType[]>([])
useEffect(() => {
getData()
}, [])
const getData = async () => {
setTimeout(() => {
const data = new Array(10).fill('標(biāo)題-').map((s,i) => (
{id: 'id-' + i, title: s + i}
))
setList(data)
}, 200);
}
const onDragEnd = (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>
)
}
注意事項(xiàng)
- 如果傳入的是一個(gè)函數(shù)式組件,需要用一個(gè)html元素包裹住
<SortListDndKit list={list} onDragEnd={onDragEnd}>
{list.map((item) => (
<SortItemDndKit>
{/* 這里需要用html元素包裹一下 */}
<div>
<Text title='測(cè)試組件' />
</div>
</SortItemDndKit>
))}
</SortListDndKit>
- 這里的排序默認(rèn)是讀取
list
中的id
作為key
值的,如果key
值是其他,可以指定list
中傳入的idKey
{/* newId:list中的id名稱 */}
<SortListDndKit idKey="newId" list={list} onDragEnd={onDragEnd}></SortListDndKit>
- 如果內(nèi)部的元素綁定了鼠標(biāo)點(diǎn)擊之類的事件,需要先阻止事件冒泡
onMouseDown={e => e.stopPropagation()}
<SortListDndKit list={list} onDragEnd={onDragEnd}>
{list.map((item) => (
<SortItemDndKit>
{/* 這里需要用html元素包裹一下 */}
<div>
<h4>這里有很多內(nèi)容</h4>
{/* 這里需要阻止鼠標(biāo)點(diǎn)擊事件的冒泡 */}
<button onMouseDown={e => e.stopPropagation()} onClick={()=>console.log('點(diǎn)擊了')} >點(diǎn)擊</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值,默認(rèn)是id */
idKey?: string;
children: ReactNode;
/** 拖拽結(jié)束的回調(diào) */
onDragEnd: (arr: any[], ids: string[]) => void;
};
/** 參考官網(wǎng):https://docs.dndkit.com/presets/sortable */
/**
* 列表排序
*/
export const SortListDndKit = ({
list = [],
idKey = 'id',
children,
onDragEnd,
}: PropsType) => {
// 指定傳感器,默認(rèn)是全部
const sensors = useSensors(
// useSensor(PointerSensor),
useSensor(MouseSensor),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
}),
);
// 拖拽結(jié)束
const handleDragEnd = (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);
const ids: 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;
};
/**
* 列表排序的子項(xiàng)
* - 函數(shù)式組件作為children,需要用html元素包裹住
* - 例:
* - \<SortItemDndKit>
* - \<div>\<Text title='測(cè)試組件' />\</div>
* - \</SortItemDndKit>
*/
export const SortItemDndKit = ({ 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)) {
return null;
}
const childProps = {
...child.props,
ref: setNodeRef,
style,
...attributes,
...listeners,
};
return React.cloneElement(child, childProps);
});
return <>{newChild}</>;
};
到了這里,關(guān)于react 基于 dnd-kit 封裝的拖拽排序組件的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!