如何给多个同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
相关产品推荐
相关产品推荐

