react中使用dnd-kit实现拖拽排序
dnd-kit
官网
入口: https://ant-design.antgroup.com/docs/react/recommendation-cn
仓库: https://github.com/clauderic/dnd-kit
官网: https://dndkit.com/
介绍
DnD-Kit(Drag and Drop Kit)是一个用于构建可拖放用户界面的React库。
它被设计为轻量级、模块化、高性能,并且易于集成到现有的React应用程序中。
DnD-Kit的主要目标是提供一个简单而强大的API来处理拖放操作,同时保持高度的可定制性和可访问性。
主要特点
- 轻量级:DnD-Kit仅包含实现拖放功能所必需的核心代码,这使得它的体积小且加载速度快。
- 模块化:库被分解成多个独立的模块,可以根据需要选择性地导入所需的组件或功能。
- 高性能:通过优化算法和利用React的特性,DnD-Kit能够高效地处理复杂的拖放场景。
- 可访问性:DnD-Kit遵循WCAG指南并支持ARIA属性,确保拖放操作对于所有用户都是可访问的。
- 可扩展性:开发者可以通过自定义传感器、识别器等来扩展DnD-Kit的功能,以适应特定的应用需求。
安装
npm install @dnd-kit/core @dnd-kit/sortable @dnd-kit/modifiers @dnd-kit/utilities --save
@dnd-kit/core
:核心库,提供基本的拖拽功能。@dnd-kit/sortable
:扩展库,提供排序功能和工具。@dnd-kit/modifiers
:修饰库,提供拖拽行为的限制和修饰功能。@dnd-kit/utilities
:工具库,提供 CSS 和实用工具函数。
使用
最基础的上下文
需要先使用 <DndContext />
组件包裹需要实现拖拽效果的组件,相当于可拖拽的范围容器
import React from 'react';
import {DndContext} from '@dnd-kit/core';
// 这些是实现的各种组件
import {Draggable} from './Draggable';
import {Droppable} from './Droppable';
function App() {
return (
<DndContext>
// 组件包裹在内
<Draggable />
<Droppable />
</DndContext>
)
}
示例
导入必要包
import type { DragEndEvent } from "@dnd-kit/core";
import { DndContext } from "@dnd-kit/core";
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
import {
arrayMove,
SortableContext,
useSortable,
/*
垂直列表使用verticalListSortingStrategy,
横向列表使用horizontalListSortingStrategy
*/
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Card } from "antd";
import * as React from "react";
import { useState } from "react";
准备数据
interface ItemType {
id: number;
name: string;
}
const App = () => {
const data: ItemType[] = [
{ id: 1, name: "列表项1" },
{ id: 2, name: "列表项2" },
{ id: 3, name: "列表项3" },
{ id: 4, name: "列表项4" },
];
const [items, setItems] = useState(data);
return (
<>
// 组件部分
// ......
</>
);
};
export default App;
实现一个可拖拽组件
interface ItemType {
id: number;
name: string;
}
const DraggableListNode = (props: ItemType) => {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
id: props.id,
});
const style = {
transform: CSS.Transform.toString(transform),
transition,
marginTop: 8,
};
return (
<Card bordered style={style} ref={setNodeRef} {...attributes} {...listeners}>
// 这里简单展示了name
{props.name}
</Card>
);
};
在组件中应用拖拽组件
const App= () => {
// 这是拖拽结束的响应方法
const handleDragEnd = ({ active, over }: DragEndEvent) => {
console.log(active);
console.log(over);
// 当拖拽前后的id不一致时,说明完成了有效的拖拽行为
if (active.id !== over?.id) {
// 对数据进行修改
const activeIndex = items.findIndex((i) => i.id === active.id);
const overIndex = items.findIndex((i) => i.id === over?.id);
const newlist = arrayMove(items, activeIndex, overIndex);
setItems(newlist);
}
};
return (
<>
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={handleDragEnd}>
<SortableContext
items={items.map((i: ItemType) => i.id)}
// 设置竖向拖拽
strategy={verticalListSortingStrategy}
>
{items.map((item: ItemType) => (
<DraggableListNode key={item.id} {...item} />
))}
</SortableContext>
</DndContext>
</>
);
};
export default App;
完整代码
import type { DragEndEvent } from "@dnd-kit/core";
import { DndContext } from "@dnd-kit/core";
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
import {
arrayMove,
SortableContext,
useSortable,
/*
垂直列表使用verticalListSortingStrategy,
横向列表使用horizontalListSortingStrategy
*/
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Card } from "antd";
import * as React from "react";
import { useState } from "react";
interface ItemType {
id: number;
name: string;
}
const DraggableListNode = (props: ItemType) => {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({
id: props.id,
});
const style = {
transform: CSS.Transform.toString(transform),
transition,
marginTop: 8,
};
return (
<Card bordered style={style} ref={setNodeRef} {...attributes} {...listeners}>
{props.name}
</Card>
);
};
const App= () => {
const data: ItemType[] = [
{ id: 1, name: "列表项1" },
{ id: 2, name: "列表项2" },
{ id: 3, name: "列表项3" },
{ id: 4, name: "列表项4" },
];
const [items, setItems] = useState(data);
const handleDragEnd = ({ active, over }: DragEndEvent) => {
console.log(active);
console.log(over);
if (active.id !== over?.id) {
console.log("active", active.id);
const activeIndex = items.findIndex((i) => i.id === active.id);
const overIndex = items.findIndex((i) => i.id === over?.id);
const newlist = arrayMove(items, activeIndex, overIndex);
setItems(newlist);
}
};
return (
<>
<DndContext modifiers={[restrictToVerticalAxis]} onDragEnd={handleDragEnd}>
<SortableContext
items={items.map((i: ItemType) => i.id)}
strategy={verticalListSortingStrategy}
>
{items.map((item: ItemType) => (
<DraggableListNode key={item.id} {...item} />
))}
</SortableContext>
</DndContext>
</>
);
};
export default App;
本文来自博客园,作者:厚礼蝎,转载请注明原文链接:https://www.cnblogs.com/guangdelw/p/18333641
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律