为什么即使拖放目标元素 class 列表属性不包含可拖动元素 ID 也会执行拖放?

Why drag and drop execute even if drop target element class list attributes doesn't contain draggable element id?

当且仅当所讨论的放置目标元素包含可拖动元素 ID 作为其 class 属性之一时,我希望将可拖动元素放入放置目标元素中。

因此,当将 id="chigaco" 的可拖动元素放入其 class 列表属性包含“chigaco”的放置目标元素时,代码会按预期执行。

当用户尝试将所述元素放入 class 列表属性不包含“chigaco”的放置目标元素时,不会执行放置。到目前为止一切顺利。

问题在于代码将可拖动元素放入具有 class 列表属性的放置目标元素中,其中包含可拖动元素 ID。但我希望我的代码什么也不做。

希望我说的有道理。如果不尝试使用“应用程序”,它将不言自明

const drags = document.querySelectorAll(".drag");
const empties = document.querySelectorAll(".empty");


for(const drag of drags) {
  drag.addEventListener("dragstart", function(e) {
    drag.classList.add("purple")
  })
  drag.addEventListener("dragend", function(e) {
    setTimeout(() => drag.classList.remove("purple"), 0)
  })

  for(const empty of empties) {
    empty.addEventListener("dragover", function(e) {
      e.preventDefault();
      console.log("dragover");
    })
    empty.addEventListener("dragenter", function(e) {
      e.preventDefault()
      console.log("dragenter")
    })
    empty.addEventListener("dragleave", function(e) {
      console.log("leave")
      console.log(empty)
    })
    empty.addEventListener("drop", function(e) {
      if(empty.classList.contains(drag.id) === false) return
      empty.append(drag)
    })
  }
}
.container {
  display: flex;

}

.empty {
  border: 1px black solid;
  height: 310px;
  width: 310px;
  margin: 10px;
  flex-direction: row;
}

.fill {
  border: 1px black solid;
  height: 100px;
  width: 100px;
  margin: 10px;
}

.drag {
  border: 1px black solid;
  height: 300px;
  width: 300px;
  margin: 10px;
  margin-left: 0;
  flex-direction: row;
}

.cointainer1 {
  margin-left: 0;
}

.parent {
  display: flex;
  flex-direction: row;
}

.purple {
  background-color: purple;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="index.css">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
    <title></title>
  </head>
  <body>
    <div class="parent">
      <div class="container1">
        <div id="chigaco" class="drag chigaco" draggable="true">bulls</div>
        <div id="losAngeles" class="drag losAngeles" draggable="true">laker</div>
        <div id="boston" class="drag boston" draggable="true">celtics</div>
        <div id="spurs" class="drag spurs" draggable="true">san Antionio</div>
        <div id="knicks" class="drag knicks" draggable="true">New York</div>
      </div>

      <div class="container2">
        <div class="empty chigaco">chigaco</div>
        <div class="empty losAngeles">losAngeles</div>
        <div class="empty boston">boston</div>
        <div class="empty spurs">spurs</div>
        <div class="empty knicks">knicks</div>
      </div>
    </div>

  </body>
  <script src="index.js" type="text/javascript">

  </script>

</html>

方法很好,但这里有两个主要错误:

  1. 嵌套的侦听器。每个 drag 向所有 empty 添加一个监听器,这些需要是两个单独的循环,否则你正在乘以监听器(拖动*空)
  2. 不存储拖动的元素,因为需要比较id和class

修复方法如下(参见 JS 代码中的注释)

const drags = document.querySelectorAll(".drag");
const empties = document.querySelectorAll(".empty");

// dragged Element
let currentDrag = null;

// Loop for drags
for(const drag of drags) {
  drag.addEventListener("dragstart", function(e) {
    drag.classList.add("purple");
    currentDrag = e.target; // Store the dragged element
  });

  drag.addEventListener("dragend", function(e) {
    setTimeout(() => {
      drag.classList.remove("purple");
      currentDrag = null; // Remove the dragged element, not required but consistent in logic
    }, 10);
  });
}

// Loop for empties
for(const empty of empties) {
  empty.addEventListener("dragover", function(e) {
    e.preventDefault();
  });

  empty.addEventListener("drop", function(e, i) {
    const dropElement = e.target; // Declaring for clarity
    if(!currentDrag || dropElement.classList.contains(currentDrag.id) === false) return
    empty.append(currentDrag);
  })
}
    .container {
      display: flex;

    }

    .empty {
      border: 1px black solid;
      height: 310px;
      width: 310px;
      margin: 10px;
      flex-direction: row;
    }

    .fill {
      border: 1px black solid;
      height: 100px;
      width: 100px;
      margin: 10px;
    }

    .drag {
      border: 1px black solid;
      height: 300px;
      width: 300px;
      margin: 10px;
      margin-left: 0;
      flex-direction: row;
    }

    .cointainer1 {
      margin-left: 0;
    }

    .parent {
      display: flex;
      flex-direction: row;
    }

    .purple {
      background-color: purple;
    }
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" integrity="sha384-DyZ88mC6Up2uqS4h/KRgHuoeGwBcD4Ng9SiP4dIRy0EXTlnuz47vAwmeGwVChigm" crossorigin="anonymous">
    <title></title>
  </head>
  <body>
    <div class="parent">
      <div class="container1">
        <div id="chigaco" class="drag chigaco" draggable="true">bulls</div>
        <div id="losAngeles" class="drag losAngeles" draggable="true">laker</div>
        <div id="boston" class="drag boston" draggable="true">celtics</div>
        <div id="spurs" class="drag spurs" draggable="true">san Antionio</div>
        <div id="knicks" class="drag knicks" draggable="true">New York</div>
      </div>

      <div class="container2">
        <div class="empty chigaco">chigaco</div>
        <div class="empty losAngeles">losAngeles</div>
        <div class="empty boston">boston</div>
        <div class="empty spurs">spurs</div>
        <div class="empty knicks">knicks</div>
      </div>
    </div>
  </body>

</html>