# Drag and drop sorting

# Final effect

TIP

This effect is the final result after adding the 'flip' effect. The last step of this article did not add 'flip'. For more information, please refer to 'flip'

Demonstration case (opens new window)

# achieve

1、Add drag and drop attributes to each li

<ul class="list">
        <li draggable="true">1</li>
        <li draggable="true">2</li>
        <li draggable="true">3</li>
        <li draggable="true">4</li>
        <li draggable="true">5</li>
        <li draggable="true">6</li>
</ul>

2、When dragging, the original position is changed to a ghost by changing the CSS

WARNING

Asynchronous operation needs to be added because the style of dragging is obtained based on the moment of dragging, so modifying CSS needs to be delayed

//Using a proxy to listen and drag
list.ondragstart = (e)=>{
    //Add an asynchronous operation because the style of the drag is the style of the original element at the moment of the drag. Adding an asynchronous operation will not change the style in advance
    setTimeout(()=>{
        e.target.classList.add('moving')
    },0)
}

3、Trigger position change when dragging to other targets

NowListNode: The currently being dragged element stored during drag

//Trigger when listening and dragging to the target
list.ondragenter = (e)=>{
    //Exclude moving above the parent element and its own element
    if(e.target=== list || e.target === nowListNode){
        return
    }
    //Convert all child elements into an array, determine the size of the index of the moved element and the index of the covered element, and determine whether to move downwards or upwards at this time
    const children=Array.from(list.children)
    const nowNodeIndex= children.indexOf(nowListNode)
    const targetIndex=children.indexOf(e.target)
    if(targetIndex>nowNodeIndex){
        //Move down to add it before the next element of that element
        list.insertBefore(nowListNode,e.target.nextElementSibling)
    }else{
        //Move up to add it to the front of the element
        list.insertBefore(nowListNode,e.target)
    }
}

4、After dragging, change CSS back

list.ondragend=(e)=>{
    e.target.classList.remove('moving')
}

5、(1) The drag operation does not allow dragging onto other elements, so some browsers may have animations that move the drag style back to its original position. This can be resolved by blocking default events. (2) The default drag operation is copy, and some browser mice will change to a plus sign, so change its behavior to move












 

 
 
 


 





















const list = document.querySelector('.list')
let nowListNode
//Using a proxy to listen and drag
list.ondragstart = (e)=>{
    //Add an asynchronous operation because the style of the drag is the style of the original element at the moment of the drag. Adding an asynchronous operation will not change the style in advance
    setTimeout(()=>{
        e.target.classList.add('moving')
    },0)
    //Record the currently being dragged dom
    nowListNode = e.target
    //Dragging defaults to copying, and some browser mice will change to a plus sign, so change its behavior to move
    e.dataTransfer.effectAllowed = 'move'
}
list.ondragover = (e)=>{
    e.preventDefault()
}
//Trigger when listening and dragging to the target
list.ondragenter = (e)=>{
    e.preventDefault()
    //Exclude moving above the parent element and its own element
    if(e.target=== list || e.target === nowListNode){
        return
    }
    //Convert all child elements into an array, determine the size of the index of the moved element and the index of the covered element, and determine whether to move downwards or upwards at this time
    const children=Array.from(list.children)
    const nowNodeIndex= children.indexOf(nowListNode)
    const targetIndex=children.indexOf(e.target)
    if(targetIndex>nowNodeIndex){
        //Move down to add it before the next element of that element
        list.insertBefore(nowListNode,e.target.nextElementSibling)
    }else{
        //Move up to add it to the front of the element
        list.insertBefore(nowListNode,e.target)
    }
}
//Trigger after listening and dragging ends
list.ondragend=(e)=>{
    e.target.classList.remove('moving')
}
上次更新: 2024/5/2 18:23:06