Vue.js 2的拖放实现

Easy-DnD (Easy-DnD)

Easy-DnD is a drag and drop implementation for Vue.js 2 that uses only standard mouse events instead of the HTML5 drag and drop API, which is impossible to work with. Think of it as a way to transfer data from some components to others using the mouse or support for a mouse assisted copy/cut - paste. It also allows for lists to be reordered by drag and drop.

Easy-DnD是Vue.js 2的拖放实现,仅使用标准鼠标事件,而不使用HTML5拖放API。 可以将它视为使用鼠标将数据从某些组件传输到其他组件的一种方式,或者支持鼠标辅助的复制/剪切-粘贴。 它还允许通过拖放对列表进行重新排序。

These demos are meant to be pretty and reflect real life examples. For more barebones examples, see the manual.

这些演示旨在使它们漂亮并反映现实生活中的示例。 有关更多准系统示例,请参见手册。

The following demo features list reordering, drag and drop between two lists, custom drag images and custom feedback when inserting new items. It uses Vuetify components.

以下演示功能将列表重新排序,在两个列表之间拖放,自定义拖动图像和自定义反馈(在插入新项目时)。 它使用Vuetify组件。

The following demo features drag and drop between a table and a list, custom drag images and a custom style for drop areas when the drop is allowed. It uses Vuetify components.

以下演示功能在允许放置的情况下在表格和列表之间拖放,自定义拖动图像和放置区域的自定义样式。 它使用Vuetify组件。

https://codesandbox.io/s/easy-dnd-demo-2-xnqbz

https://codesandbox.io/s/easy-dnd-demo-2-xnqbz

Vue.js 2的拖放实现

总览 (Overview)

There are four components : Drag, Drop, DropMask and DropList.

有四个组件:Drag,Drop,DropMask和DropList。

The Drag component is meant to define an area from which data can be exported. The Drop component is meant to define an area into which data can be imported. Drop components can be nested forming hierarchies of arbitrary depth. The DropMask component is meant to create an island insensitive to drag and drop on top of a Drop component. The DropList component is a special kind of drop component that displays a list of items that supports dragging into and reordering.

Drag组件用于定义可以从中导出数据的区域。 Drop组件用于定义可以将数据导入到的区域。 拖放组件可以嵌套形成任意深度的层次结构。 DropMask组件旨在创建一个对Drop组件不敏感的孤岛。 DropList组件是一种特殊的放置组件,它显示支持拖动和重新排序的项目列表。

大事记 (Events)

All events carry the current state of the drag operation by means of the following properties :

所有事件均通过以下属性来携带拖动操作的当前状态:

  • type : the type of the data being transferedtype :要传输的数据的类型
  • data : the data being transfereddata :正在传输的数据
  • position : the current position of the mouse cursorposition :鼠标光标的当前位置
  • top : the foremost Drop component currently under the mouse cursor if anytop :当前鼠标光标下方的第一个Drop组件(如果有)
  • previousTop : for dragenter and dragleave, the previous value of top if anypreviousTop :对于Dragenter和Dragleave,top的上一个值(如果有)
  • source : the Drag component where the drag originatedsource :拖动起源的Drag组件

Drag components emit the following events :

拖动组件会发出以下事件:

  • dragstart : triggered when a drag operation startsdragstart :拖动操作开始时触发
  • dragend : triggered when a drag operation terminates (whether successfuly or not)dragend :在拖动操作终止时触发(是否成功)
  • cut / cut / copy : triggered when a drag operation completes successfuly on a Drop component that requires the data to be removed / copiedcopy :在需要删除/复制数据的放置组件上的拖动操作成功完成时触发

Drop components emit the following events :

Drop组件会发出以下事件:

  • dragenter : triggered when the mouse enters a Drop componentdragenter :当鼠标进入Drop组件时触发
  • dragleave : triggered when the mouse leaves a Drop componentdragleave :当鼠标离开Drop组件时触发
  • dragover : triggered when the mouse moves over a Drop componentdragover :当鼠标移到Drop组件上时触发
  • drop : triggered when a drop operation completes on a Drop componentdrop :在Drop组件上完成放置操作时触发

DropList components emit the following events (in addition to the ones emitted by Drop components) :

DropList组件发出以下事件(除了Drop组件发出的事件之外):

  • insert : triggered when data is to be inserted into the list (properties : type, data and index)
  • insertinsert数据插入列表时触发(属性: typedataindex
  • reorder : triggers when data needs to be reordered (properties : reorder :在需要对数据进行重新排序时触发(属性: from, fromto and toapply - apply is a function that applies the required reordering to the given array)apply -apply是将所需的重新排序应用于给定数组的函数)

数据 (Data)

Export : the data being exported when a drag operation originates from a Drag component is defined by mean of its data property.

导出:当拖动操作源自Drag组件时,要导出的数据是通过其data属性定义的。

Import : when a drag operation terminates in a Drop components, its drop event is triggered and the event carries the data to be imported.

导入:当拖动操作终止于Drop组件时,将触发其drop事件,并且该事件携带要导入的data

模式 (Modes)

A drag and drop can occur in several possible modes, depending on its effect on the origin of the drag :

拖放可能会以几种可能的方式发生,具体取决于其对拖动源的影响:

  • copy (the default) : if the source of the drag is unaffected by the drag operation,copy (默认):如果拖动源不受拖动操作的影响,
  • cut : if the source of the drag is to be removed when the drag operation completes.cut :如果拖动操作完成后要删除拖动源。

Drop components must declare what mode must be triggered when data is dropped into them using the mode property.

放置组件必须声明使用mode属性将数据放入它们时必须触发哪种模式。

When a drag operation completes on a Drop component that declares the cut (respectively copy) mode, a cut (respectively copy) event is emitted on the Drag component from which the drag operation originated. This gives the opportunity to the surroundings of the Drag component to react to the drop that just happened, for example by removing the data that has been dropped in case of the cut event.

当声明了一个Drop部件上的拖动操作完成cut (分别copy )模式, cut (分别copy )事件被发射从该拖动操作起源于将组件上。 这使Drag组件的周围环境有机会对刚刚发生的删除做出React,例如,通过删除在cut事件的情况下删除的数据。

If a drag operation originates from a Drag components that doesn't declare a listener for the cut event, then dropping is forbidden on a Drop component that declares the cut mode.

如果拖动操作源自未为cut事件声明侦听器的Drag组件,则在声明cut模式的Drop组件上禁止放置。

The following demo illustrates modes in action :

以下演示说明了运行中的模式:

https://codesandbox.io/s/example-2-r8n1k

https://codesandbox.io/s/example-2-r8n1k

Vue.js 2的拖放实现

种类 (Types)

A drag operation may have a type. The type is a data structure (can be a simple string) that defines the kind of data being transfered. The type of a drag operation is defined by the Drag component that initiates it using the type prop.

拖动操作可以具有一种类型。 类型是一个数据结构(可以是简单的字符串),它定义了要传输的数据的类型。 拖动操作的类型由使用type属性启动它的Drag组件定义。

A Drop component is said to participate in a drag operation if it accepts its type (the default is to accept any type). The type(s) a Drop component accepts can be defined by mean of the accepts-type prop (can be a string, an array of strings or a function that takes the type as parameter and returns a boolean).

如果Drop组件接受其类型(默认值为接受任何类型),则称其参与了拖动操作。 Drop组件可以accepts-type可以通过accepts-type prop定义(可以是字符串,字符串数组或以该类型为参数并返回布尔值的函数)。

As far as Easy-DnD is concerned, if a Drop component doesn't accept the type of the current drag operation, it behaves like any other part of the page that is not sensitive to drag and drop. It is ignored during the drag, no special CSS classes are applied, no special cursors / drag images are displayed and no special events are triggered.

就Easy-DnD而言,如果Drop组件不接受当前拖动操作的类型,则其行为类似于页面上对拖放不敏感的任何其他部分。 在拖动过程中将忽略它,不应用特殊CSS类,不显示特殊的光标/拖动图像,也不会触发特殊事件。

The following demo illustrates the use of types. There are two types in use : 'string' and 'number'. The Drag components that contain '1' and '2' are of type 'number', the ones containing 'a' and 'b' are of type 'string'. The two Drop components on the left accept numbers, the ones on the right accept strings. When you drag a number/string (respectively), only Drop components that accept numbers/strings (respectively) react (i.e. drag images, CSS classes, cursors are applied). The other ones are left alone.

以下演示说明了类型的用法。 使用两种类型:“字符串”和“数字”。 包含“ 1”和“ 2”的Drag组件的类型为“数字”,包含“ a”和“ b”的组件的类型为“字符串”。 左侧的两个Drop组件接受数字,右侧的两个接受字符串。 当您分别拖动数字/字符串时,只有分别接受数字/字符串的Drop组件会做出React(即拖动图像,CSS类,光标被应用)。 其他的则一个人呆着。

https://codesandbox.io/s/example-3-g7io8

https://codesandbox.io/s/example-3-g7io8

Vue.js 2的拖放实现

限制可放置数据 (Restricting droppable data)

Drop components can restrict the data they accept by mean of the accepts-data prop (a function that takes the data and type as parameter and returns a boolean).

Drop组件可以通过accepts-data属性(将数据和类型作为参数并返回布尔值的函数)来限制其accepts-data

The following demo defines five Drag components that can be dragged into three Drop components, one that accepts even numbers, one that accepts odd numbers and one that accepts any number but removes them once the drag is complete.

下面的演示定义了五个Drag组件,可以将它们拖动到三个Drop组件中,一个可以接受偶数,一个可以接受奇数,一个可以接受任何数字,但拖动完成后将其删除。

https://codesandbox.io/s/easy-dnd-demo-fo078

https://codesandbox.io/s/easy-dnd-demo-fo078

Vue.js 2的拖放实现

滑鼠游标 (Mouse cursor)

If a drag isn't in progress, the cursor turns into grab when the mouse is over a Drag component. If a drag is in progress, the cursor turns into grabbing, unless it is over a Drop component that accepts the type of the current drag operation. Then, it turns into pointer if the Drop component accepts the data being dragged, and into not-allowed otherwise.

如果没有进行拖动,则当鼠标悬停在“拖动”组件上时,光标将变为“ grab状态。 如果正在进行拖动,则光标将变为“ grabbing ,除非光标位于接受当前拖动操作类型的Drop组件上。 然后,如果Drop组件接受被拖动的数据,它将变为pointer ,否则变为not-allowed

拖曳图片 (Drag image)

During the drag, an image may move along the mouse cursor. Easy-DnD makes it so that this image is always on top of everything else.

在拖动过程中,图像可能会沿着鼠标光标移动。 Easy-DnD可以使此图像始终位于其他所有内容之上。

Drag components provide the drag-image slot that can be used to set the default image displayed during the drag operation :

拖动组件提供了drag-image插槽,可用于设置拖动操作期间显示的默认图像:

  • if the slot isn't defined, the image is a clone of the Drag component.

    如果未定义插槽,则该图像是Drag组件的克隆。
  • if the slot is defined and empty, there is no image.

    如果插槽已定义且为空,则没有图像。
  • if the slot is not empty, a clone of its content is used.

    如果插槽不为空,则使用其内容的副本。

Drop and DropList components provide the drag-image slot (props : data and type) that can be used to set the image to be displayed when the mouse is over them, if they participates in the current drag operation (i.e. accept its type) :

降和DropList组件提供drag-image槽:(道具datatype ,当鼠标在它们,如果它们在当前的拖动操作参与将要显示可用于设置图像)(即接受其类型):

  • if the slot isn't defined, the default image set by the Drag component is used.

    如果未定义插槽,则使用“拖动”组件设置的默认图像。
  • if the slot is defined and empty, there is no image.

    如果插槽已定义且为空,则没有图像。
  • if the slot is not empty, a clone of its content is used.

    如果插槽不为空,则使用其内容的副本。

DropList components additionaly provide the reordering-drag-image slot (prop : item subject to reordering) that behaves the same way as drag-image but controls the drag image to be displayed during list reordering.

DropList组件还提供了reordering-drag-image插槽(prop:要重新排序的item ),其行为与drag-image相同,但是控制拖动图像在列表重新排序期间显示。

The position of the drag image relative to the mouse cursor can be controlled by CSS using the transform property.

拖动图像相对于鼠标光标的位置可以通过CSS使用transform属性来控制。

The following demo illustrate the use of custom drag images, nested Drop components and a mask :

以下演示说明了自定义拖动图像,嵌套的Drop组件和遮罩的用法:

https://codesandbox.io/s/example-4-6h8zy

https://codesandbox.io/s/example-4-6h8zy

Vue.js 2的拖放实现

CSS类 (CSS classes)

A Drag component is assigned the class drag-in when the mouse is over it and a drag operation isn't in progress, drag-out otherwise. Depending on the mode of the Drop component currently under the mouse cursor, the source Drag component is also assigned the classes drag-mode-copy, drag-mode-cut and drag-mode-reordering.

拖动组件被分配的类drag-in当鼠标在它和拖动操作没有在进行, drag-out否则。 根据当前在鼠标光标下的Drop组件的模式,还为源Drag组件分配了drag-mode-copydrag-mode-cutdrag-mode-reordering

During a drag operation, the Drop components on the page are assigned several CSS classes :

在拖动操作期间,页面上的Drop组件被分配了几个CSS类:

  • type-allowed if the Drop component accepts the type of the drag operation, type-allowed ,如果掉落组件接受拖动操作的类型, type-forbidden otherwisetype-forbidden否则
    • drop-in when the mouse is over one that is foremost at the current mouse position (remember Drop components can be nested), drop-in当鼠标在一个是最重要的,在当前鼠标位置(记得掉落部件可以嵌套), drop-out otherwisedrop-out ,否则
    • drop-allowed when the Drop component accepts the data and the source of the drag accepts its mode, drop-allowed当掉落组件接受所述数据和所述拖动源接受其模式, drop-forbidden otherwisedrop-forbidden否则

DropMask组件 (DropMask component)

The following demo illustrates the use of a DropMask :

以下演示说明了DropMask的用法:

https://codesandbox.io/s/example-1-ngrlv

https://codesandbox.io/s/example-1-ngrlv

Vue.js 2的拖放实现

DropList组件 (DropList component)

The DropList component is a special Drop component so it inherits all the props and events of the Drop component. It can be used when the result of a drag operation is to import data into the component as an item in a list at a specific index or to allow the user to reorder a list of items using drag and drop.

DropList组件是一个特殊的Drop组件,因此它继承了Drop组件的所有道具和事件。 当拖动操作的结果是将数据作为列表中特定索引处的项导入到组件中时,或者允许用户使用拖放对项列表进行重新排序时,可以使用它。

Comparing to the Drop component, there is one more prop :

与Drop组件相比,还有一个道具:

  • items : the array of items to be rendereditems :要渲染的项目数组

Comparing to the Drop component, there are two more events :

与Drop组件相比,还有两个事件:

  • insert : emitted when the user drops data into the DropList. If no listener is provided for this event, the list cannot be inserted into.insert :当用户将数据放入DropList时发出。 如果没有为此事件提供侦听器,则无法将列表插入其中。
  • reorder : emitted when the user reorders the list. If no listener is provided for this event, the list cannot be reordered.reorder :当用户重新排序列表时发出。 如果没有为此事件提供侦听器,则无法重新排序列表。

Comparing to the Drop component, there are three more slots :

与Drop组件相比,还有三个插槽:

  • item : used to render each list item. It has two properties, item :用于呈现每个列表项。 它具有两个属性, item and itemreorder. Reorder is true when the item is the one subject to reordering. reorder 。 当项目是要重新排序的商品时,重新排序为true。 Don't forget to provide a key for the content of this slot !!不要忘记提供此插槽内容的**!
  • feedback : used to render a placeholder to show the position where the new item would be inserted if the drag operation ended at the current mouse position. It has two properties : feedback :用于呈现一个占位符,以显示在拖动操作在当前鼠标位置结束时要插入新项目的位置。 它具有两个属性: type and typedata. dataDon't forget to provide a key for the content of this slot !!不要忘记提供此插槽内容的**!
  • reordering-drag-image : defines the drag image to be used when reordering the list (see drag image section above).reordering-drag-image :定义在对列表重新排序时要使用的拖动图像(请参见上面的拖动图像部分)。

Keys on items and feedback are used to disallow the drop if it would create duplicates and result in errors.

如果项目和反馈上的键会创建重复项并导致错误,则使用该键禁止其放置。

The following demo features drag and drop from one list to another and list reordering.

以下演示功能从一个列表拖放到另一个列表,并对列表重新排序。

https://codesandbox.io/s/droplist-ozs8b

https://codesandbox.io/s/droplist-ozs8b

Vue.js 2的拖放实现

标签 (Tags)

Drag and Drop components support the tag prop that can be used to control the HTML tag (or Vue component) that will serve as root of the template. In case of tags that are Vue components, all props, listeners and slots function as they normally would.

拖放组件支持tag属性,该属性可用于控制将用作模板根目录HTML标签(或Vue组件)。 如果标签是Vue组件,则所有道具,侦听器和插槽均会正常运行。

DragAwareMixin (DragAwareMixin)

A mixin is available to make components sensitive to drag operations. It adds the following computed fields to components that incorporate it, reflecting the current state of the drag :

可以使用mixin使组件对拖动操作敏感。 它将以下计算字段添加到合并该字段的组件中,以反映拖动的当前状态:

  • dragInProgress : true if a drag operation is in progress, false otherwisedragInProgress :如果正在进行拖动操作,则为true,否则为false
  • dragType : the type of the current drag operationdragType :当前拖动操作的类型
  • dragData : the data of the current drag operationdragData :当前拖动操作的数据
  • dragPosition : the current position of the mouse relative to the documentdragPosition :鼠标相对于文档的当前位置
  • dragSource : the Drag component from which the drag operation originateddragSource :拖动操作源自的Drag组件
  • dragTop : the foremost Drop component under the mouse if anydragTop :鼠标下方最重要的Drop组件(如果有)

The following demo displays information about the current drag operation when it is in progress :

以下演示显示了有关当前拖动操作的信息:

https://codesandbox.io/s/example-5-j8qo9

https://codesandbox.io/s/example-5-j8qo9

Vue.js 2的拖放实现

翻译自: https://vuejsexamples.com/a-drag-and-drop-implementation-for-vue-js-2/