React-dnd: 支持拖动多个元素

创建于 2014-10-25  ·  30评论  ·  资料来源: react-dnd/react-dnd

有一个常见的模式很难通过原生拖放实现:拖动多个元素。 虽然选择机制可能因应用程序而异(cmd+单击、复选框、预定义组),但至少让它_可能_支持这种情况会很好。

screen shot 2014-10-26 at 1 07 07

因为多个拖动的项目可能不是 DOM 中的兄弟,而且setDragImage(element, x, y)非常疯狂并且没有变得更好,我们不会因为尝试在拖动预览中同时渲染多个元素而造成负担。

如果我们不能显示“多个”拖动预览,我们如何帮助实现这个场景?

在某种程度上,这种情况已经成为可能:消费者可以手动跟踪所选元素,将dragPreview为某种通用占位符Image并对丢弃的(就业务而言)做出适当的反应逻辑方面)几个要素。

但是,目前没有支持的方式让一个元素知道它是被拖动的组的一部分。 从 react-dnd 的角度来看,如果我们拖动某个东西,这个组件会得到getDragState(type).isDragging = true ,但其他组件不会。 从您的应用程序的角度来看,如果您支持多项选择,您希望所有逻辑上“选定”的项目都知道它们正在被拖动,即使实际上只有其中一个被“DOM 拖动”。

我们需要的是一种让组件告诉 react-dnd 的方法,“嘿,虽然onDragStart被另一个组件接收了,但我想假装我也被拖拽了,并让我的getDragState(type)镜像拖动组件的getDragState(type) ,并调用我的endDrag(didDrop)以便我可以做我的事情”。

组件将如何选择?

design decisions

最有用的评论

如果有人感兴趣,我实现了一个多拖动/网格视图: https :
您可以使用 cmd/ctrl 和 shift 键选择多个项目,然后在网格周围拖动它们并将它们插入到任何位置。

这仍然是一个演示,但我可能会稍微抽象一下代码,然后将其打包到一个组件中。

所有30条评论

不是优先事项。 我们可以在引入拖动源密钥后重新访问(https://github.com/gaearon/react-dnd/issues/38#issuecomment-73409935)。

我会对此感兴趣,尽管我认为您可能只需将组件树的一部分与具有 dragSource 的组件包装起来...
就像你按住 shift 并单击一样,它会扩展数组的哪些部分被复制到 dragItem 或其他东西中?

有点。

首先,我们学习传递 null component (#38 所需)和具有相同key (#53 所需)的不同组件。

然后我们添加groupKey这是可选的。 和key ,它在拖动源中指定并且是一个字符串。 当您开始使用groupKey拖动某物时,我们不仅会在调用者上调用beginDrag groupKey ,还会在每个已安装的具有相同groupKey拖动源上调用,并将它们的项目收集到数组。 我们将传递这些项目而不是item来删除目标方法。 当拖动结束时,我们将使用项目数组在放置目标上调用acceptDrop ,然后使用它们的项目调用每个拖动源的endDrag

有趣的是,我们可以使用自定义的“复合”缩略图组件和我上面截图的计数器来绘制DragLayer ,因为我们知道items.length的计数。

那是一个比我心目中的更不丑陋的想法

:+1: 对于此功能:-)

结束,因为我目前没有这方面的用例,这是一项重要的实施工作。

@gaearon

以前我使用 Java/Swing DnD,他们可能有一大批开发人员解决了这个问题,并提出了一个非常精致、非常通用和灵活的框架。 我建议研究旧的桌面框架,因为它们可能解决了制作这样一个好的 DnD 框架的所有困难挑战。

在 Java/Swing 中执行此操作的方法(尽管它没有对拖动图像的内置支持)是_使树视图本身成为拖动源_,并使其 _能够根据其决定是否应启动拖动当前状态和拖动开始位置_。 调用canDragbeginDragmonitor.getInitialSourceClientOffset()可用? 人们肯定希望它可用。 他们可能还希望修改键(ctrl、alt、shift)可用,并且能够使拖动源指定是移动还是复制,以及放置目标以指定它们是否支持移动和/或复制,基于任何这些因素,因为这在 Java/Swing 中是可能的,我猜测其他框架。 Swing 还具有可以替换的 _drag 手势识别器_ 的概念。

我预测将列表中的所有项目视为单独的可拖动对象与将列表组件作为单个拖动源相比会很困难,后者根据其中选择的内容确定要构建的放置有效负载/预览图像的类型。

还要考虑到开发人员可能希望_更改被拖动项目的顺序,具体取决于用户单击和拖动的项目。_ 我相信 Windows 资源管理器的行为方式是这样的。

有没有人在他们的应用程序中使用 react-dnd 实现拖动多个项目? 您目前对此的解决方案是什么?

您是说单个拖动源的多个放置目标吗?

+1 @danii1 :有没有人实现拖动多个项目?

我实现了它,解决方案基本上是第一篇文章中描述的:

  1. 跟踪您选择的项目
  2. 实现 CustomDragLayer(请参阅 https://gaearon.github.io/react-dnd/docs-drag-layer.html)并自己呈现您选择的项目
  3. 如果放置的项目是选择的一部分,则处理放置

我通过以下方式实现它:

  1. 跟踪集合中的选定项目
  2. 将此作为属性传递给 dnd 源
  3. 在 beginDrag 中检索 Set 形式的道具并将其作为拖动项返回
  4. 创建自定义拖动预览
  5. 在 EndDrag 上将 Set 中的所有项目移动到 dnd Target

我有一个稍微不同的用例,我想,我想绘制可拖动的节点,边缘不可拖动,但当节点连接到移动时会移动。 我当前的实现是一个CustomDragLayer ,它在检测到DraggableNode正在移动时绘制边缘(也在CustomDragLayer上绘制,但我认为将其建模为通过将所有边实现为 DragSources 来实现多重拖动情况,并实现isDragging()以检测它们所连接的节点是否正在移动,以便它们可以绘制自己,而不是让CustomDragLayer将坐标注入作为道具.

@danii1
您能否分享您已实施的一个以供参考

我将写一篇文章并添加关于使用 react-dnd + redux 的多个和嵌套拖放的 repo。

@nayemmajhar ,那会很棒

@nayemmajhar关于这个例子的任何更新?

我很久以前就使用 react DnD 和 reduxJS 开发了这个应用程序https://www.joomshaper.com/page-builder我正在写一个教程,但需要时间发布

@serle你能分享一个你是如何做到的代码示例吗?

@ianmclean2011在这里查看: https :

我试图在类似于这里的可排序示例的示例中实现多拖动: https :

如果有人感兴趣,我实现了一个多拖动/网格视图: https :
您可以使用 cmd/ctrl 和 shift 键选择多个项目,然后在网格周围拖动它们并将它们插入到任何位置。

这仍然是一个演示,但我可能会稍微抽象一下代码,然后将其打包到一个组件中。

@melvynhills您是否研究过不需要将所有选定的卡片传递给每个卡片组件的解决方案? 考虑到卡片的 beginDrag() 需要对所有选定卡片的引用,我认为没有解决方案。

@jmcrthrs不,我似乎不可能使用 react-dnd API。 我认为在拖动将要拖动哪个特定项目之前没有办法知道。 这也是了解拖动的项目是否在您所做的多项选择内,或者是否在我们需要替换的选择之外的唯一方法。

@melvynhills @jmcrthrs我使用

@jedwards1211你认为这个库可行吗? 特别是开始拖动在拖动开始之前未选择的项目的用例。 我不确定这是 react-dnd 应该工作的方式。

有人解决了有多个放置目标的情况吗?
假设一个正在拖动多个项目(使用上述解决方案之一),一个项目最终位于一种类型的放置目标上,而另一个则位于不同的目标上。 drop将只为发起拖动的拖动源触发,而不会为另一个触发。 任何想法如何为每个被移动的项目单独触发丢弃。
例子:
Is development slow, Online Whiteboard for Visual Collaboration 2019-11-27 10-45-33

编辑:为此创建单独的问题https://github.com/react-dnd/react-dnd/issues/1650

@melvynhills可能如果mousedown处理程序触发项目选择(您应该这样做,我使用过的所有带有 DnD 的软件都以这种方式工作),它将与 React DnD 一起工作,以便容器组件成为拖动源,因为拖动事件将在mousedown

您是否研究过不需要将所有选定的卡片传递给每个卡片组件的解决方案?

这是为什么我建议将容器组件作为拖动源而不是单个项目的示例。 我不需要使用 React DnD 实现多选,但也许有时我可以制作一个沙箱来说服人们这是更易于维护的方法

有没有人在他们的应用程序中使用 react-beautiful-dnd 实现拖动多个项目? 您目前对此的解决方案是什么?

此页面是否有帮助?
0 / 5 - 0 等级