You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何给多个同class元素添加事件监听?拖拽滚动功能失效排查

问题分析与修复方案

你的代码无法实现多容器拖拽滚动的核心问题有三个:

1. 事件参数传递错误

你在绑定事件时错误地将DOM元素box传给了处理函数,但事件处理函数的第一个参数应该是事件对象e,而非元素本身。同时你需要通过事件对象获取当前触发事件的容器元素。

2. 全局变量导致多容器状态冲突

startY、startX、scrollLeft、scrollTop这些状态变量被定义为全局的,当操作多个容器时,它们的值会被互相覆盖,导致拖拽逻辑混乱。需要为每个容器单独维护这些状态。

3. 错误引用NodeList而非单个容器

原代码中container是querySelectorAll返回的节点列表,你在mouseIsDown等函数里直接使用container.offsetTop这类属性是完全错误的,必须引用当前操作的单个容器元素。


修复后的完整代码

HTML(无需修改)

<div class="container boxes" id="items-container">
  <div class="item"> </div>
  <div class="item"></div>
  <div class="item" style="width: 150%;">  </div>
  <div class="item"> </div>
  <div class="item"></div>
  <div class="item" style="width: 150%;"> </div>
  <div class="item"> </div>
  <div class="item"> </div>
  <div class="item" style="width: 150%;"> </div>
  <div class="item"> </div>
  <div class="item"> </div>
  <div class="item" style="width: 150%;"> </div>
</div>
<div class="container boxes">
  <div class="item"> </div>
  <div class="item"></div>
  <div class="item" style="width: 150%;">  </div>
  <div class="item"> </div>
  <div class="item"></div>
  <div class="item" style="width: 150%;"> </div>
  <div class="item"> </div>
  <div class="item"> </div>
  <div class="item" style="width: 150%;"> </div>
  <div class="item"> </div>
  <div class="item"> </div>
  <div class="item" style="width: 150%;"> </div>
</div>

CSS(无需修改)

body{
  margin:0;padding:15px; font-family: sans-serif;
  font-size: 1.2em;
}
.container{
  background: #333;display: grid;
  grid-template-columns: auto auto auto;
  padding:8px;box-sizing:border-box;
  height: 500px;overflow:auto;
}
.item{
  width: 90%;
  height: 60px;
  margin:60px;
  display:flex;
  justify-content:center;
  align-items:center;
  color:#FFFFFF;
}
.item:nth-child(even){
  background: #30a57f;
}
.item:nth-child(odd){
  background:#c17a38;
}

修复后的JS

const containers = document.querySelectorAll('.boxes');

// 为每个容器单独绑定事件和状态
containers.forEach(container => {
  // 将状态变量绑定到当前容器元素上,避免全局冲突
  container.startY = 0;
  container.startX = 0;
  container.scrollLeftVal = 0;
  container.scrollTopVal = 0;
  container.isDown = false;

  container.addEventListener('mousedown', mouseIsDown);
  container.addEventListener('mouseup', mouseUp);
  container.addEventListener('mouseleave', mouseLeave);
  container.addEventListener('mousemove', mouseMove);
});

function mouseIsDown(e) {
  const container = e.currentTarget;
  container.isDown = true;
  container.startY = e.pageY - container.offsetTop;
  container.startX = e.pageX - container.offsetLeft;
  container.scrollLeftVal = container.scrollLeft;
  container.scrollTopVal = container.scrollTop;
}

function mouseUp(e) {
  e.currentTarget.isDown = false;
}

function mouseLeave(e) {
  e.currentTarget.isDown = false;
}

function mouseMove(e) {
  const container = e.currentTarget;
  if (container.isDown) {
    e.preventDefault();
    // 垂直滚动
    const y = e.pageY - container.offsetTop;
    const walkY = y - container.startY;
    container.scrollTop = container.scrollTopVal - walkY;

    // 水平滚动
    const x = e.pageX - container.offsetLeft;
    const walkX = x - container.startX;
    container.scrollLeft = container.scrollLeftVal - walkX;
  }
}

关键修改说明

  • 将状态变量绑定到每个容器元素本身(如container.startY),避免全局变量带来的多容器冲突问题。
  • 事件处理函数中通过e.currentTarget获取当前操作的容器,确保每个容器的拖拽逻辑独立。
  • 修正事件绑定的参数传递,确保事件对象正确传入处理函数。

内容的提问来源于stack exchange,提问作者Justin C

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 13:57:54