background



@TOC


The first step is the MDN drag method summary, if not interested can be skipped.

In the spirit of doing everything without importing packages, I gave up using vue plugins (too many packages to import and too much redundant code) and chose to use H5 native for this function


What are the official drag-and-drop methods and attributes?

First let’s take a look at some summary of drag-and-drop methods on MDN.

1. Draggable property

In HTML, elements are not draggable by default, except for images, links, and selected text that are draggable by default. To make other HTML elements draggable, you must do three things:

1. Set draggable to draggable=”true” for the element you want to drag

2. Todragstart ()Event adds a listener

3. Set drag and drop data in the listener defined in the previous step

	<p draggable="true" 
	   ondragstart="event.dataTransfer.setData('text/plain', 'This text may be dragged')">This text<strong>can</strong>Drag and drop.</p>
Copy the code

2. Start the dragstart operation

When the user starts dragging, dragStart () is triggered. The event in this example, dragstart (). Event listeners are added to the dragable element itself; However, you can listen for an ancestor element because drag events bubble up like most other events.

In dragstart (). In the event, you can specify drag data, feedback images, and drag effects, all of which are described below. However, we only need to set the drag data, because the default image and drag effects will apply in most cases.

	<p draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'This text may be dragged')">This text<strong>can</strong>Drag and drop.</p>
Copy the code

3. Drag the data dataTransfer

All drag events have a property called dataTransfer,

It holds drag data (dataTransfer is a dataTransfer object). This property takes two parameters, in short, the first parameter is the type you allow drag and drop, and the second parameter is the data to place to the specified link

Event. The dataTransfer. SetData (" text/plain ", "can drag and drop text");Copy the code
  • You can also provide multiple types of data, as follows:
	const dt = event.dataTransfer;
	dt.setData("application/x.bookmark", bookmarkString);
	dt.setData("text/uri-list", "http://www.abc.org");
	dt.setData("text/plain", "http://www.abc.org");
Copy the code
  • If you add them repeatedly in the same format, the new data will replace the old data, and you can clear them, as follows:
	event.dataTransfer.clearData("text/uri-list");
Copy the code

4. Set drag feedback image setDragImage

When a drag occurs, a translucent image of the drag target (the element that triggers the “{event(“dragstart”)}” event) is generated and the mouse pointer is tracked during the drag. This image is automatically created, so you don’t need to create it yourself. However, you can customize drag feedback images using the setDragImage() method.

	event.dataTransfer.setDragImage(image, xOffset, yOffset);
Copy the code
  • All three parameters are necessary. The first is the image reference. This reference is usually one<img>The element

But it could also be

or any other element. The resulting feedback image is what the image looks like on the screen, drawn in its original size. The second and third arguments to the setDragImage() method are the offset of the image position relative to the mouse pointer position. You can also use images and canvases that are not in the document. This technique is useful when drawing custom drag-and-drop feedback images using the Canvas element, as in the following example:

```html function dragWithCustomImage(event) { var canvas = document.createElementNS("http://www.w3.org/1999/xhtml","canvas"); canvas.width = canvas.height = 50; var ctx = canvas.getContext("2d"); ctx.lineWidth = 4; ctx.moveTo(0, 0); ctx.lineTo(50, 50); ctx.moveTo(0, 50); ctx.lineTo(50, 0); ctx.stroke(); var dt = event.dataTransfer; Dt.setdata ('text/plain', dragged data '); dt.setDragImage(canvas, 25, 25); In this example, we made a drag image that is a canvas. When the canvas is 50 pixels wide and 50 pixels high, we use half offsets (25 and 25) so that the mouse pointer is the center of the image.Copy the code

5. The drag effect effectalhoward

Some actions may be performed during the drag-and-drop process.

The copy operation is used to indicate that the data being dragged will be copied from the current location to the drop location.

The move operation indicates that the dragged data will be moved,

The link operation indicates that some form of relationship or connection will be created between the source and the placement.

The Effectalhoward property can be set in the dragstart () event listener to specify which of the three operations the drag source is allowed to perform.

	event.dataTransfer.effectAllowed = "copy";
Copy the code
The above code example is copy-only, you can implement your requirements in different ways: Copy: copy only 3. Move only 4. Link: link only 5. CopyMove: copy or move 6. CopyLink: copy or link 7Copy the code

6. Specify the target dragover to place

The listener for the dragenter () or dragover () event is used to indicate the valid drop target, where the dragged item might be placed. Most areas of a web page or application are not efficient places to put data. Therefore, the default handling of these events is not allowed to be placed.

If you want to allow placement, you must cancel the Dragenter and Dragover events to prevent the default processing. You can do this by returning false in the event listener defined by the property, or by calling the event preventDefault() method. In a function defined in a separate script, the latter may be more feasible.

<div ondragover="return false">
<div ondragover="event.preventDefault()">
Copy the code

7. Place feedback – Moz-drag-over CSS

There are several ways to indicate to the user where placement is allowed. The mouse pointer will be updated as necessary based on the value of the dropEffect property. The appearance of the mouse pointer depends on the user’s platform, typically a plus icon will appear in ‘copy’, and a forbidden icon will appear when it is not allowed to be placed. In many cases, mouse pointer feedback is sufficient.

However, you can also update the user interface as needed, such as adding an insert mark or using highlighting. For simple highlighting, you can use the -moz-drag-over CSS pseudo-class on the placement target.

.droparea:-moz-drag-over {
  border: 1px solid black;
}
Copy the code

Note: For this pseudo-class to take effect, the preventDefault() method must be added to the Dragenter event

8. Run the drop command

When the user releases the mouse, the drag-and-drop operation ends.

If you release the mouse over a valid drop target element (that is, an element that undragenter () or dragover ()), the drop succeeds and the drop () event is fired on the target element. Otherwise the drag is cancelled and the drop () event is not triggered.

The domxref(“DragEvent. DataTransfer “,”dataTransfer”) property of the event always holds the drag data for all drag-related events. The getData() method is used to retrieve the data.

function onDrop(event) {
  const data = event.dataTransfer.getData("text/plain");
  event.target.textContent = data;
  event.preventDefault();
}
Copy the code

8. Complete the drag dragend

Once the drag is complete, the dragend () event occurs at the source of the drag, the element that triggered the dragstart (). This event is raised whether the drag is successful or cancelled. However, you can use the dropEffect property to decide what drop operations to perform. If the dropEffect attribute is None in the dragend () event, drag is cancelled. Otherwise, this property dictates what needs to be done. The source element can use this information to remove the dragged item from its original location after the drag operation is complete. The mozUserCancelled () property is set to true when the user cancels the drag (by pressing the Esc key) and false when the drag is cancelled for some other reason, such as an invalid place target, or when the drag succeeds.

Placement can occur in the same window or in another application. In both cases, the dragend () event is triggered. The screenX and screenY properties of the event are set to place the coordinates of the mouse on the screen when it occurs.

After the event(“dragend”) event ends, the entire drag-and-drop operation is complete.

Two, start implementation

1. After summarizing the drag method, drag – start – enter – end should be the normal process

No single event can fulfill my business requirements, but a combination can, so I used the following events

  1. dragstart You know which element is being dragged by the index passed to the function
  2. dragenter Use index to know which element was entered last
  3. dragend The logic is executed as soon as the element is placed, exchanging data from the dragged element with data from the last element placed
  4. dragover Undrag the drag disable button for child elements by disabling the default attribute for the parent

So I added the following code (sample) :

	<view
		@dragstart="dragstart(index)"
		@dragenter.prevent="dragenter($event, index)"
		@dragend="dragend($event, index)"> Drag test code </view>Copy the code

The corresponding function is:

		dragstart(index) {
			console.log(index)
			this.startIndex = index;// Store the subscript at the beginning of the drag
		},
		dragenter(e, index) {
			console.log(e,index)
			this.endIndex = index;// Store the subscript at the end of the drag to know which element was entered last
		},
		dragend(e, index) {
			console.log(e,index)
			let { startIndex, endIndex } = this; // There is a start and end of the data directly to the corresponding value can be exchanged
		},
Copy the code

It is worth noting that when exchanging data with third-party variables, it is recommended to use a deep copy to the data source for replication. However, the bidirectional binding of arrays and objects in Vue2.0 is always hard.

$set(‘ data must exist ‘,’ which attribute ‘,’ data source ‘)

2. It’s getting better

Thankfully, the basic drag sorting for the easy version is now almost complete, but there was a problem: when I was dragging, there was a disabled icon. I realized that something must be wrong, and after searching the document in several places, I found the reason for this: The parent of the dragged element must disable the attribute that prevents it from being placed by default, so the code is modified and the resulting code looks like this:

<view  @dragover.prevent="allowDrop($event)">
	<view
		@dragstart="dragstart(index)"
		@dragenter.prevent="dragenter($event, index)"
		@dragend="dragend($event, index)"</view> </view>Copy the code
		dragstart(index) {
			console.log(index)
			this.startIndex = index;// Store the subscript at the beginning of the drag
		},
		dragenter(e, index) {
			console.log(e,index)
			this.endIndex = index;// Store the subscript at the end of the drag to know which element was entered last
		},
		dragend(e, index) {
			console.log(e,index)
			let { startIndex, endIndex } = this; // There is a start and end of the data directly to the corresponding value can be exchanged
		},
		allowDrop(e){
			e.preventDefault()  // Disable the parent element's attribute that prevents placement by default, so that the element can be placed (no disabled icon appears)
		},
		
Copy the code

3. Call it a day

Since each person has different business needs, the specific logic should be written by himself. The example of finished product is as follows:

Due to recording software reasons, the drag process of the animation is compressed by default, it appears that the animation is not smooth, there is no way, because it is a white piao


conclusion

A good memory is not as good as a bad pen to record the status of the project in real time. It is also very beautiful when you want to recall it later

Tomorrow, another day full of hope!

Put a town map at the end