vue Realizes Picture Drag Sorting

  • 2021-11-29 06:10:07
  • OfStack

This article example for everyone to share the vue picture dragging sort of the specific code, for your reference, the specific content is as follows

Principle: There is a list of 1 picture. Drag one picture (trigger dragstart). When the dragged picture moves to the position of other pictures (trigger dragover), the dragged picture will move from the original position to the position (trigger dragend).

dragstart: The dragstart event is triggered when the user starts dragging an element or a selection text.

dragover: Triggers the dragover event (every few hundred milliseconds) when an element or selected text is dragged onto a valid drop target.

dragend: The drag-and-drop event is triggered at the end of the drag-and-drop operation. (We don't need it here.)

(1) Image list HTML structure. Add the attribute draggable to the element that needs to be dragged. It should be noted here that the key value of template for loop needs to be only 1, because vue will be reused locally when rendering. If key value is only 1, the rendered list nodes will not be reused after reordering, which can avoid some problems. (When we insert, we insert some data into the array according to the sequence number.)


 <ul class="drag-container" 
            @dragstart="onDragStart"
            @dragover="onDragOver"
            @dragend="onDragEnd"
            ref="imgList">
            <li 
            v-for="(item,idx) in list" 
            :key='item.path'
            class="drag-list" 
            draggable="true" 
            >
                <img :src="item.path" alt="" />
            </li>
</ul>

(2) Events: dragstart, dragover Bind Events onDragStart, onDragOver

onDragStart: Identifies the element to be dragged and saves it to state for use by dragover binding events during dragging.


onDragStart(event){
            console.log("start");
            this.draging = event.target;
        }, 

onDragOver: Triggers when the drag is on a valid target, identifying the target element, not the dragged element. First, identify whether the target element is the target element we need. Our example judges whether it is an li element, and judges whether the picture is the same as the drag, then insert the drag element.
Identify the position sequence number of the drag element and the target element, insert the drag element into the target element, and then delete the data at the original position of the drag element. In vue, only data operation is needed.


onDragOver(event){
            console.log('drag move')
            event.preventDefault();
            let target = event.target;
                // Because dragover Will happen in ul On, so we have to judge whether it is li
            if (target.nodeName === "LI" && 
                target.childNodes[0].src !== this.draging.childNodes[0].src) {
                let idx_drag = this._index(this.draging)
                let idx_target = this._index(target)
                let _list = this.list
                let _drag = this.list[idx_drag]
                if(idx_drag>idx_target){
                    _list.splice(idx_target,0,_list[idx_drag]);
                    _list.splice(idx_drag+1,1)
                }else{
                    _list.splice(idx_target+1,0,_list[idx_drag]);
                    _list.splice(idx_drag,1)
                }
                console.log(_list[0].path)
                this.$emit("change", _list)
            }
        },

The complete code is as follows:


<template>
    <div class="image-list" v-if="list && list.length">
        <ul class="drag-container" 
        @dragstart="onDragStart"
        @dragover="onDragOver"
        @dragend="onDragEnd"
        ref="imgList">
            <li 
            v-for="(item,idx) in list" 
            :key='item.path'
            class="drag-list" 
            draggable="true" 
            >
                <img :src="item.path" alt="" />
            </li>
        </ul>
    </div>
</template>
<script>
export default {
    name:"drag-image-list",
    props:{
        list: Array,
    },
    data(){
        return {
            draging:null,// Drag object 
        }
    },
    methods:{
        onDragStart(event){
            console.log("start");
            this.draging = event.target;
        },   
        onDragOver(event){
            console.log('drag move')
            event.preventDefault();
            let target = event.target;
                // Because dragover Will happen in ul On, so we have to judge whether it is li
            if (target.nodeName === "LI" && target.childNodes[0].src !== this.draging.childNodes[0].src) {
                let idx_drag = this._index(this.draging)
                let idx_target = this._index(target)
                let _list = this.list
                let _drag = this.list[idx_drag]
                if(idx_drag>idx_target){
                    _list.splice(idx_target,0,_list[idx_drag]);
                    _list.splice(idx_drag+1,1)
                }else{
                    _list.splice(idx_target+1,0,_list[idx_drag]);
                    _list.splice(idx_drag,1)
                }
                console.log(_list[0].path)
            }
        },
        onDragEnd(event){
            console.log('end event')
        },
        _index(el){
            var index = 0;
            if (!el || !el.parentNode) {
                return -1;
            }
            while (el && (el = el.previousElementSibling)) {
                index++;
            }
            return index;
        },
    }
}
</script>

Related articles: