简体   繁体   English

Javascript 在容器中拖放文件:如何防止`dragover`被多次调用导致延迟?

[英]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.现在,当我将文件拖到容器中然后放下时, "preventDefaults: dragover"会反复调用几秒钟。

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/ 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.我已经查看了其他一些关于 SO 的问题,但它们都指向使用preventDefaultstopPropagation ,但我已经准备好了。

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 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.我已经在 Chrome 和 Firefox 中尝试了您的代码。两者似乎都可以正常工作并且不会造成任何延迟。 The dragover event is supposed to fire while a file over the container ( MDN ). dragover事件应该在容器上有文件时触发 ( MDN )。

In the sample code you linked the dragover event is also fired just like yours, but it isn't printed to the console.在您链接的示例代码中, dragover事件也像您的事件一样被触发,但它没有打印到控制台。 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.您可以尝试完全删除您的console.log语句,或更改您的代码以不记录dragover事件。

Actually, I now realize you are talking about the JSFiddle console.实际上,我现在意识到您在谈论 JSFiddle 控制台。 It appears that the console there is not able to keep up with the amount of console.log calls.那里的控制台似乎跟不上console.log调用的数量。 Either refrain from logging dragover events or download your code from JSFiddle and open it in your browser.要么避免记录dragover事件,要么从 JSFiddle 下载代码并在浏览器中打开它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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