简体   繁体   中英

Javascript drag and drop file in container: how to prevent `dragover` from being called many times causing delay?

I am implementing a simple drag and drop of files in container concept. Right now, when I drag a file into the container and then drop it, the "preventDefaults: dragover" keeps getting called for few seconds repeatedly.

If I drag the file and instantly drop it, then it calls it a few times with a second or 2 delay. If I drag the file and then move it around above the container a few times and then drop it, then it calls it thousands of times with many seconds delay and the browser freezes too.

Here's the demo:

https://jsfiddle.net/4105uexo/

Make sure to click on console at the bottom right to see the log.

I have looked at a few other questions on SO but they all point to using preventDefault and stopPropagation but I already have that in place.

I am using this sample code which seems to use exactly what I am doing but for some reason mine isn't working:

https://codepen.io/joezimjs/pen/yPWQbd

My code:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }

        body {
            padding: 0;
            margin: 0;
            background: black;
            height: 100%;
            width: 100%;
        }

        x-dragdropview {
            height: 100%;
            width: 100%;

        }

        x-dragdropview .drag-drop {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            box-sizing: border-box;
            width: 100%;
            height: 100%;
            font-size: 50pt;
            color: white;
            display: none;
            border: 2pt dashed red;
        }
    </style>
</head>

<body>
    <x-dragdropview>
        <div style="display: flex; width: 100%; height: 100%; justify-content: center;
    align-items: center; font-size: 50pt; color: white;"><span>DRAG / DROP HERE</span></div>
    </x-dragdropview>
    <script>
        var dragTarget
        function preventDefaults(e) {
            console.log("preventDefaults: " + e.type);
            e.preventDefault()
            e.stopPropagation()
        }
        class XDragDropView extends HTMLElement {
            constructor() {
                super()
                this.style.display = 'block'
                this.style.position = 'relative'
                this.insertAdjacentHTML('beforeend', `<div class="drag-drop"></div>`)

                Array.from(['dragenter', 'dragover', 'dragleave', 'drop']).forEach(eventName => {
                    this.addEventListener(eventName, preventDefaults, false)
                })

                Array.from(['dragenter', 'dragover']).forEach(eventName => {
                    this.addEventListener(eventName, highlight, false)
                })

                Array.from(['dragleave', 'drop']).forEach(eventName => {
                    this.addEventListener(eventName, unhighlight, false)
                })

                function highlight(e) {
                    if (e.type == "dragenter") {
                        dragTarget = e.target
                        this.querySelector('.drag-drop').style.display = 'flex'
                        console.log("highlight: " + e.target)
                    }
                }

                function unhighlight(e) {
                    if (e.target === dragTarget) {
                        this.querySelector('.drag-drop').style.display = 'none'
                        dragTarget = null
                        console.log("unhighlight: " + e.target)
                    }
                }
                this.addEventListener('drop', handleDrop, false)
            }
        }
        window.customElements.define('x-dragdropview', XDragDropView)

        function handleDrop(e) {
            console.log(e.dataTransfer.files[0])
        }
    </script>
</body>

</html>

I've tried your code in Chrome and Firefox. Both appear to work fine and does not cause any delay. The dragover event is supposed to fire while a file over the container ( MDN ).

In the sample code you linked the dragover event is also fired just like yours, but it isn't printed to the console. Does that page slow down your browser also?

You could try removing your console.log statement completely, or change your code to not log dragover events.

Actually, I now realize you are talking about the JSFiddle console. It appears that the console there is not able to keep up with the amount of console.log calls. Either refrain from logging dragover events or download your code from JSFiddle and open it in your browser.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM