本篇主要是 dnd-kit 官方文档 中 Droppable 的对照翻译
翻译主要使用 DeepL 翻译,再根据自己的理解进行修改,如有错误,欢迎指正。 部分名词不会翻译。
使用 useDroppable
将 DOM 节点设置为 droppable 区域,draggable 元素可以被放置在上面。
Usage
useDroppable
钩子对你应该如何构造你的应用程序没有意见。
但至少,您需要将 useDroppable
返回的 setNodeRef
函数传递给一个 DOM 元素,以便它能够注册底层 DOM 节点并跟踪它,以检测与其他 draggable 元素的碰撞和交集。
如果你对ref的概念感到陌生,我们建议你先看看 React文档网站上的Refs和DOM文章
import {useDroppable} from '@dnd-kit/core';
function Droppable() {
const {setNodeRef} = useDroppable({
id: 'unique-id',
});
return (
<div ref={setNodeRef}>
/* Render whatever you like within */
</div>
);
}
你可以设置任意数量的 `droppable 容器,只要确保它们都有一个唯一的id,这样它们就可以被区分开来。不过,每个 droppable 都需要有自己独特的节点,所以要确保你不要试图将一个 droppable 连接到多个 refs。
要设置多个 droppable 目标,只需根据需要多次使用 useDroppable
function MultipleDroppables() {
const {setNodeRef: setFirstDroppableRef} = useDroppable({
id: 'droppable-1',
});
const {setNodeRef: setsecondDroppableRef} = useDroppable({
id: 'droppable-2',
});
return (
<section>
<div ref={setFirstDroppableRef}>
/* Render whatever you like within */
</div>
<div ref={setsecondDroppableRef}>
/* Render whatever you like within */
</div>
</section>
);
}
如果你需要动态地渲染一个 droppable 容器的列表,我们建议你创建一个可重复使用的 Droppable 组件,并根据需要多次渲染该组件。
function Droppable(props) {
const {setNodeRef} = useDroppable({
id: props.id,
});
return (
<div ref={setNodeRef}>
{props.children}
</div>
);
}
function MultipleDroppables() {
const droppables = ['1', '2', '3', '4'];
return (
<section>
{droppables.map((id) => (
<Droppable id={id} key={id}>
Droppable container id: ${id}
</Droppable>
))}
</section>
);
}
关于 useDroppable
的更多细节用法,请参考API文档部分。
useDroppable
Arguments
interface UseDroppableArguments {
id: string | number;
disabled?: boolean;
data?: Record<string, any>;
}
Identifier
id 参数类型为字符串或数字,它应该是一个唯一标识符,也就是说,在一个给定的 DndContext
provider 中,不应该有其他共享相同标识符的 droppable 元素。
如果你正在构建一个同时使用 useDroppable
和 useDraggable
的组件,它们可以共享同一个标识符,因为droppable元素与draggable元素储存在不同的键值存储中。
Disabled
由于钩子不能被条件调用,如果你需要暂时禁用一个可下拉的区域,请使用 disabled
参数并将其设置为 true
。
Data
数据参数是用于高级的使用情况,你可能需要在事件处理程序、修改器或自定义传感器中访问关于 droppable
元素的额外数据。
例如,如果你正在建立一个可排序的预设,你可以使用 data
属性来存储可排序列表中的 droppable 元素的索引,以便在一个自定义传感器中访问它。
const {setNodeRef} = useDroppable({
id: props.id,
data: {
index: props.index,
},
});
另一个更高级的例子是在 draggable 节点和 droppable 区域之间创建关系,例如,指定你的 droppable 区域接受哪些类型的 draggable 节点。
import {DndContext, useDraggable, useDroppable} from '@dnd-kit/core';
function Droppable() {
const {setNodeRef} = useDroppable({
id: 'droppable',
data: {
accepts: ['type1', 'type2'],
},
});
/* ... */
}
function Draggable() {
const {attributes, listeners, setNodeRef, transform} = useDraggable({
id: 'draggable',
data: {
type: 'type1',
},
});
/* ... */
}
function App() {
return (
<DndContext onDragEnd={handleDragEnd}>
/* ... */
</DndContext>
);
function handleDragEnd(event) {
const {active, over} = event;
if (over && over.data.current.accepts.includes(active.data.current.type)) {
// do stuff
}
}
}
Properties
{
rect: React.MutableRefObject<LayoutRect | null>;
isOver: boolean;
node: React.RefObject<HTMLElement>;
over: {id: UniqueIdentifier} | null;
setNodeRef(element: HTMLElement | null): void;
}
Node
setNodeRef
为了使 useDroppable
能够正常工作,它需要将 setNodeRef
属性附加到你打算变成 droppable 区域的 HTML 元素上。
function Droppable(props) {
const {setNodeRef} = useDroppable({
id: props.id,
});
return (
<div ref={setNodeRef}>
{/* ... */}
</div>
);
}
node
传递给 setNodeRef 的当前节点的 ref
rect
对于高级的用例,如果你需要 droppable 区域的边界矩形测量。
Over
isOver
使用 useDroppable
返回的布尔值 isOver
来改变 draggable 元素被拖到你的 droppable 容器上时显示的外观或内容。
over
如果您想在 draggable 元素被拖到不同的 droppable 容器上时改变 draggable 元素的外观,请检查是否定义了 over
值。根据您的使用情况,你也可以读取其他 draggable 元素 的id,对你的 droppable 组件的渲染输出进行修改。