dragleave 上冒泡事件的问题

问题描述 投票:0回答:3

我有一个工作示例,其中包含

dragenter
dragleave
事件,突出显示应放置文件的区域。此示例工作正常

现在,如果我只是在我的 Dragenter 区域内添加一个

<span>
突出显示将不再正常工作(当您将图像悬停在文本顶部时 - 突出显示消失)。如您所见,
dragleave
被调用了多次。

我所做的一切更改都是将

Drop files here
替换为
<span>Drop files here</span>

那里也有淘汰码,但我相信它与该错误无关。我知道问题出在事件冒泡上,但是

   e.stopPropagation();
   e.preventDefault();
   return false;

没有帮助。知道如何让它与内部 dom 元素一起工作吗?

P.S.这只是一个简化的例子,看起来我无法正确制作它(我认为通过JS解决它的唯一方法,看来我描述的方式是可以解决的也可以使用 css)。很抱歉造成这种混乱。示例看起来更像是this。不仅文本位于可放置元素的内部,而且当您放置某些内容时,元素也会出现在那里。这些元素是可点击的。

Malk 解决方案的问题在于

:after
元素停留在这些可点击元素的顶部,从而使它们不可点击。

javascript jquery css knockout.js
3个回答
2
投票

看起来您可以将处理程序附加到位于跨度之后和之上的覆盖 div:

<div class="col-md-12" data-bind="foreach: dropZones">
    <div class="drop_zone">
        <span>Drop files here</span>
        <div class="drop_zone_overlay" data-bind="event:{
                dragover:   function(data, e){ $root.dragover(e);},
                drop:       function(data, e){ $root.drop(e, $data);},
                dragenter:  function(data, e){ $root.dragenter(e, $index());},
                dragleave:  function(data, e){ $root.dragleave(e, $index());}
            }">
          </div>
    </div>
    <ul data-bind="foreach: elements" style="height: 100px">
        <li data-bind="text: $data"></li>
    </ul>
</div>

CSS

.drop_zone {
    border: 2px dashed #bbb;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;
    padding: 25px;
    text-align: center;
    font: 20pt bold'Vollkorn';
    color: #bbb;

    position:relative;
}

.drop_zone_overlay { 
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
}

http://jsfiddle.net/rWWK5/


编辑

实际上你根本不需要添加其他元素。您可以使用 CSS

:after
创建一个伪元素,它应该能够覆盖内容。

.drop_zone {
    ...
    position:relative;
}
.drop_zone:after{
    content:'';
    position:absolute;
    top:0;
    left:0;
    right:0;
    bottom:0;
}

http://jsfiddle.net/ewng9/


编辑2

您可以使用此技术仅在拖动时覆盖内容。您只需将

.css({})
调用更改为
toggleClass()
并将
:after
放在新类上即可。

http://jsfiddle.net/dKsmw/

这还可以让您创建一个为背景元素着色的叠加层:

.drop_zone_hover:after{
    ...
    background-color:#0f0;
    opacity:0.6;
}

1
投票

我认为马尔克的回答是有效的。使用覆盖层或遮罩位于放置区域上方,当您拖放时它是子区域。这可以防止您在使用

span

时遇到的问题

我用你最新的例子创建了一个工作的Fiddle


0
投票

我遇到了这个问题。而且,与大多数问题一样,它们可以用 javascript 解决。

像OP一样,我也不想让一个元素覆盖整个拖放区并使可点击的元素呈现惰性。

本质上,只需确保鼠标位置位于容器的边界框内即可。

dragleave
事件处理程序中,使用
currentTarget
获取
getBoundingClientRect
的边界框。

拖动事件将具有代表鼠标位置的

clientX
clientY
属性。

检查鼠标位置是否位于放置区的

top
right
bottom
left
边缘内。如果它在边界框内,则尽早返回并且不再处理
dragleave
事件。

const handleDragLeave = e => {
  if (isInsideContainer(e)) return
  e.currentTarget.classList.remove("dragged-over")
}

const isInsideContainer = e => {
  const { top, bottom, left, right } = e.currentTarget.getBoundingClientRect()
  return e.clientX < right && e.clientX > left && e.clientY > top && e.clientY < bottom
}

const dropzone = document.querySelector(".dropzone")

dropzone.addEventListener("dragenter", e => {
  e.currentTarget.classList.add("dragged-over")
})

dropzone.addEventListener("dragleave", handleDragLeave)
* {
  box-sizing: border-box;
}

body {
  min-height: 100vh;
  display: grid;
  place-items: center;
}

.dropzone {
  border: 2px dashed black;
  padding: 3rem;
  display: grid;
  place-items: center;
}

.dragged-over {
  border-color: limegreen;
  background-color: lightgrey;
}

span {
  border: 1px solid blue;
}
<div class="dropzone">
  <span>Drag and drop here</span>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.