装置
官方文档:docs.dndkit.com/presets/sor… > 运用 @dnd-kit 只需求装置他的中心库@dnd-kit/core 就够了 >
npm install @dnd-kit/core
或许
yarn add @dnd-kit/core
@dnd-kit/core 有大多数用户在构建拖放体会时最需求的主要功能
@dnd-kit/modifiers 动态修正坐标
@dnd-kit/sortable 排序专用
运用
1.需求引进 DndContext 组件,他类似 react 的 Context 向下传递状态,他必须在拖拽组件的最外层
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>
);
}
2.运用 useDroppable 创立一个能够坠落的区域
运用 ref 传递给您希望成为可坠落的 DOM 元素
传入仅有的 id
import React from "react";
import { useDroppable } from "@dnd-kit/core";
function Droppable(props) {
const { isOver, setNodeRef } = useDroppable({
id: "droppable",
});
const style = {
color: isOver ? "green" : undefined,
};
return (
<div ref={setNodeRef} style={style}>
{props.children}
</div>
);
}
3.运用 useDraggable 创立一个能够拖动的元素
运用 ref 传递给可拖拽的 DOM 元素
传入仅有的 id
import React from 'react';
import {useDraggable} from '@dnd-kit/core';
function Draggable(props) {
const {attributes, listeners, setNodeRef, transform} = useDraggable({
id: 'draggable',
});
const style = transform ? {
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
} : undefined;
return (
<button ref={setNodeRef} style={style} {...listeners} {...attributes}>
{props.children}
</button>
);
}
}
说明
DndContext
该 供给程序运用 React Context API 在可拖动和可放置的组件和钩子之间同享数据
可嵌套运用
Props
都是选填
- id:仅有标识
- autoScroll:操控主动翻滚的行为。能够是一个布尔值,表示是否启用主动翻滚,默以为 true;也能够是一个函数,用于自界说主动翻滚的行为。
- onDragStart(e):拖动开端时触发的回调函数。
- e.active:拖动的元素信息{data,id,rect}
- onDragMove(e):拖动过程中触发的回调函数
- onDragOver(e):拖动过程中鼠标悬停在某个区域时触发的回调函数
- onDragEnd(e):拖动完毕时触发的回调函数
- e.active:拖动的元素信息
- e.over:drop(接纳拖拽元素)的元素信息
- onDragCancel(e):拖动被撤销时触发的回调函数,按下 esc 键会撤销
- collisionDetection:指定碰撞检测算法的函数,默以为依据鸿沟框的 AABB (Axis-Aligned Bounding Box) 碰撞检测算法。
- sensors:详情见后面的传感器。他一个数组,包括要运用的传感器。传感器用于捕捉拖放操作的各种事情。默许情况下,传感器包括 MouseSensor、TouchSensor 和 KeyboardSensor。你能够依据需求挑选性地启用或禁用传感器。
- modifiers:一个数组,包括要运用的润饰器。润饰器用于修正拖放行为的办法。默许情况下,润饰器包括 RestrictToVerticalAxisModifier 和 RestrictToHorizontalAxisModifier。你能够依据需求挑选性地启用或禁用润饰器。
useDroppable
需求将 useDroppable 钩子回来的 setNodeRef 函数传递给 DOM 元素
要设置多个可放置方针,只需依据需求屡次运用 useDroppable 钩子即可
你能够运用这些回来值来依据拖动项是否放置在可放置区域上方来修正组件的样式或触发其他逻辑。例如,你能够依据 isOver 来显示一个放置指示器,或许依据 isOverCurrent 来修正放置区域的背景色。
需求注意的是,useDroppable 只能在可放置区域的直接子元素上运用。假如你想将其应用于更深层级的元素上,能够运用 useDroppableOverlay 钩子。
参数,是一个目标
- id(string,必填):仅有标识可放置区域的 ID。
- data(恣意类型):可选的自界说数据,能够在放置事情中运用。
- disabled(boolean):可选,用于禁用可放置区域。
回来值,回来一个目标
- setNodeRef:用于绑定可坠落的元素的 ref
- active:当时拖动元素的信息
- node:当时可放置区域的 DOM 节点
- rect:回来的是表示当时 Droppable 组件鸿沟框的 DOMRect 目标
- top:鸿沟框的上边际相对于视口的 y 坐标
- right:鸿沟框的右边际相对于视口的 x 坐标
- bottom:鸿沟框的下边际相对于视口的 y 坐标
- left:鸿沟框的左边际相对于视口的 x 坐标
- width: 矩形的宽度。
- height: 矩形的高度
- isOver:是否有拖拽元素滑动在该元素上,和 css 中的 hover 相同
- over:drop(接纳拖拽元素)的元素信息
useDraggable
需求将 useDroppable 钩子回来的 setNodeRef 函数传递给 DOM 元素
需求用 style 里的 transform 特点来操控元素的方位
需求把回来值里的 listeners 传递给 DOM 元素 例如
<button ref={setNodeRef} style={style} {...listeners} {...attributes}>
建议将回来值 attributes 传递给 DOM 元素
参数,是一个目标
- id:必填,仅有标识符
- disabled:是否禁用
- data:该元素的自界说数据
- attributes:
回来值,回来一个目标
-
setNodeRef:用于绑定可坠落的元素的 ref
-
node:当时拖动的 dom 元素
-
isOver:是否有拖拽元素滑动在该元素上,和 css 中的 hover 相同
-
over:drop(接纳拖拽元素)的元素信息
-
active:当时拖动元素的信息
- id:当时元素 id
- data:当时元素参数里的 data
- rect:
-
isDragging:是否正在拖动
-
activeNodeRect:当时拖动的 dom 元素
-
attributes:建议传递给 DOM 元素,详情见docs.dndkit.com/api-documen…
-
listeners:拖动手柄,需求传递给 DOM 元素才能拖动
-
transform:拖动的鼠标移动信息
- x:x 坐标移动间隔
- y:y 坐标移动间隔
- scaleX:x 轴缩放
- scaleY:y 轴缩放
- css 帮助程序
CSS.Translate.toString(transform) === `translate3d(${translate.x}, ${translate.y}, 0)`; //运用 import { CSS } from "@dnd-kit/utilities"; const style = { transform: CSS.Translate.toString(transform), };
DragOverlay
他是一个组件,当开端拖动时,他会显示到拖动的组件上面,拖动完毕就会隐藏
即便不加 style 也能够拖动,useDraggable 必须加 style 才会移动
该叠加从正常文档流中删去并相对于视区定位
<DragOverlay>
<div>234234</div>
</DragOverlay>
Sensors (传感器)
传感器是一种抽象概念,用于检测不同的输入办法,以便发动拖动操作、呼应移动以及完毕或撤销操作。
传感器担任监督用户的手势、拖动元素和方针元素之间的交互,并将交互事情传递给 DndContext 组件
import { DndContext, useSensor } from "@dnd-kit/core";
function MyComponent() {
const sensor = useSensor(/* 传感器装备参数 */);
return <DndContext sensors={[sensor]}>{/* 其他组件 */}</DndContext>;
}
内置传感器包括
- Pointer(指针)(Pointer 是一个广义的术语,用于表示用户输入设备,能够是鼠标、接触屏、手写笔等)
- 鼠标
- 接触
- 键盘
传感器的生命周期如下
- 检测到激活器事情,假如该事情合格,则初始化传感器类。
- 传感器在初始化时手动将新侦听器连接到输入办法。
- 一旦满意约束,传感器就会分配拖动发动事情。
- 传感器发送拖动移动事情以呼应输入。
- 传感器发送拖动完毕或拖动撤销事情。
- 传感器被拆除并整理手动连接的事情侦听器。
运用传感器
默许情况下, DndContext 运用指针和键盘传感器
假如要改用其他传感器(例如鼠标和接触传感器),请运用要运用的选项 useSensor 别离初始化这些传感器
import {
DndContext,
KeyboardSensor,
MouseSensor,
TouchSensor,
useSensor,
useSensors,
} from '@dnd-kit/core';
function App() {
const sensors = useSensors(
useSensor(MouseSensor),
useSensor(TouchSensor),
useSensor(KeyboardSensor),
);
return (
<DndContext sensors={sensors}>
{/* ... */}
</DndContext>
)
}
Pointer(指针)
Modifiers(润饰器)
运用修正器能够动态修正传感器检测到的移动坐标
装置
npm install @dnd-kit/modifiers
运用
import { DndContext, DragOverlay } from "@dnd-kit";
import {
restrictToVerticalAxis,
restrictToWindowEdges,
} from "@dnd-kit/modifiers";
function App() {
return (
<DndContext modifiers={[restrictToVerticalAxis]}>
{/* ... */}
<DragOverlay modifiers={[restrictToWindowEdges]}>{/* ... */}</DragOverlay>
</DndContext>
);
}
内置的润饰符
- restrictToHorizontalAxis:将移动约束在水平轴上。
- restrictToVerticalAxis:将移动约束为仅笔直轴。
- restrictToWindowEdges:将移动约束在窗口的边际。此修正器可用于防止 DragOverlay 移动到窗口鸿沟之外。
- restrictToParentElement:约束移动到可拖动项目的父元素。
- restrictToFirstScrollableAncestor:将移动约束为拾取的可拖动项目的第一个可翻滚先人。
网格对齐
运用 createSnapModifier 创立网格,参数是网格巨细
import {createSnapModifier} from '@dnd-kit/modifiers';
const gridSize = 20; // pixels
const snapToGridModifier = createSnapModifier(gridSize);
<DndContext onDragStart={onDragStart} onDragEnd={onDragEnd} modifiers={[snapToGridModifier]}>
排序专用
装置
yarn add @dnd-kit/sortable
运用
需求把useSortable的回来值attributes和listeners传入组件
import React, { useState } from "react";
import { DndContext, useDroppable, useDraggable ,DragOverlay} from "@dnd-kit/core";
import {SortableContext,useSortable} from '@dnd-kit/sortable';
import { CSS } from "@dnd-kit/utilities";
export default function App() {
const [items,setItems] = useState<number[]>([1,2,3,4])
const onDragEnd =(e)=>{
console.log('end',e);
}
return (
<DndContext onDragEnd={onDragEnd}>
<SortableContext items={items}>
</SortableContext>
</DndContext>
);
}
function SortableItem({id}) {
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
} = useSortable({id});
const style = {
transform: CSS.Transform.toString(transform),
transition,
};
return (
<div ref={setNodeRef} style={style} {...attributes} {...listeners}>
{id}0000000
</div>
);
}
SortableContext
和 DndContext 相同用于同享数据
为了使 SortableContext 组件正常运行,请确保它是 DndContext 供给程序的子孙
能够在同一父DndContext中嵌套多个SortableContext组件
import React, { useState } from "react";
import { DndContext } from "@dnd-kit/core";
import { SortableContext } from "@dnd-kit/sortable";
export default function App() {
const [items] = useState([1, 2, 3]);
return (
<DndContext>
<SortableContext items={items}>{/* ... */}</SortableContext>
</DndContext>
);
}
props
- disabled:禁用
- items:必填每个可排序项相关的仅有标识符的排序数组,必须按照渲染项目的相同次序进行排序
- strategy:排序战略,内置战略包
- rectSortingStrategy :这是默许值,适用于大多数用例。此战略不支撑虚拟化列表。
- verticalListSortingStrategy :此战略针对笔直列表进行了优化,并支撑虚拟化列表。
- horizontalListSortingStrategy :此战略针对水平列表进行了优化,并支撑虚拟化列表。
- rectSwappingStrategy :运用此战略实现可交换功能
import {verticalListSortingStrategy} from '@dnd-kit/sortable';
<SortableContext items={items} strategy={verticalListSortingStrategy}>
- id:仅有标识
useSortable
参数
传入一个目标
- id:必填,仅有标识符
- disabled:是否禁用
- transition:要彻底禁用过渡,请将 transition 参数设置为 null
回来值
回来一个目标
- active:
- listeners:父 DndContext 供给程序上界说的每个传感器的激活器事情处理程序
- attributes:
- transform:
- setNodeRef
arrayMove
用于计算排序方位
import React, { useState } from "react";
import { DndContext} from "@dnd-kit/core";
import {SortableContext,useSortable,arrayMove} from '@dnd-kit/sortable';
import { CSS } from "@dnd-kit/utilities";
export default function App() {
const [items,setItems] = useState<number[]>([1,2,3,4])
function handleDragEnd(event) {
const {active, over} = event;
if (active.id !== over.id) {
setItems((items) => {
const oldIndex = items.indexOf(active.id);
const newIndex = items.indexOf(over.id);
return arrayMove(items, oldIndex, newIndex);
});
}
}
return (
<DndContext onDragEnd={handleDragEnd}>
<SortableContext items={items}>
{items.map(item=><SortableItem id={item}/>)}
</SortableContext>
</DndContext>
);
}