如何让水平滚动纯JS代码作用于页面所有同类元素而非仅第一个?
解决多水平滚动区域的功能问题(纯JavaScript实现)
我完全懂你现在的处境——习惯了jQuery的写法,转纯JS时踩了几个典型小坑:比如只选中第一个滚动容器,还有不知道怎么精准操作触发事件的容器的子元素。咱们一步步来把这些问题搞定:
核心问题拆解
- 仅第一个滚动区域生效:原代码用
document.querySelector('.items')只会抓取页面中第一个匹配的元素,后面的滚动容器根本没绑定事件,自然没法工作。 - 全局操作所有
.item:原代码里的links是页面所有.item的集合,滚动时会给所有元素加noclick类,这显然不是你想要的;你需要的是只操作触发mousedown的那个容器的子元素,对应jQuery里的$(this).children('.item')逻辑。
纯JavaScript完整解决方案
下面是修改后的代码,我会逐段解释关键改动:
修复后的JavaScript代码
// 获取页面中所有的.items滚动容器 const sliders = document.querySelectorAll('.items'); // 遍历每个容器,为它们单独绑定事件 sliders.forEach(slider => { // 每个容器维护自己的滚动状态变量 let isDown = false; let startX; let scrollLeft; slider.addEventListener('mousedown', (e) => { isDown = true; slider.classList.add('active'); startX = e.pageX - slider.offsetLeft; scrollLeft = slider.scrollLeft; // 替代jQuery的$(this).children('.item'):仅操作当前触发事件的容器的子元素 const currentItems = slider.querySelectorAll('.item'); currentItems.forEach(item => item.classList.add('noclick')); }); slider.addEventListener('mouseleave', () => { isDown = false; slider.classList.remove('active'); // 离开容器时移除当前容器内.item的noclick类 const currentItems = slider.querySelectorAll('.item'); currentItems.forEach(item => item.classList.remove('noclick')); }); slider.addEventListener('mouseup', () => { isDown = false; slider.classList.remove('active'); // 松开鼠标时移除当前容器内.item的noclick类 const currentItems = slider.querySelectorAll('.item'); currentItems.forEach(item => item.classList.remove('noclick')); }); slider.addEventListener('mousemove', (e) => { if (!isDown) return; e.preventDefault(); const x = e.pageX - slider.offsetLeft; const walk = (x - startX) * 3; // 滚动速度倍数 slider.scrollLeft = scrollLeft - walk; }); });
HTML代码(保持原结构不变)
<div class="items"> <div class="item item1"></div> <div class="item item2"></div> </div> <div class="items"> <div class="item item3"></div> <div class="item item4"></div> </div> <div class="items"> <div class="item item5"></div> <div class="item item6"></div> </div>
关键改动说明
- 选中所有滚动容器:用
document.querySelectorAll('.items')获取页面中所有匹配的滚动容器,再通过forEach遍历,为每个容器单独绑定事件,确保每个区域都能独立工作。 - 精准操作当前容器的子元素:
- 在
mousedown事件中,用slider.querySelectorAll('.item')获取当前触发事件的容器下的所有.item子元素,这就对应了jQuery里$(this).children('.item')的逻辑(如果.item都是直接子元素,也可以用slider.children,但querySelectorAll支持更复杂的选择器,灵活性更高)。 - 在
mouseleave和mouseup事件中,同样只操作当前容器的子元素,移除noclick类,避免影响其他区域的元素交互。
- 在
- 独立状态变量:把
isDown、startX、scrollLeft放在forEach的回调函数内部,让每个滚动容器都拥有自己的状态变量,不会出现多个容器状态互相干扰的问题。
这样修改后,每个.items区域都能独立实现点击拖动滚动,而且只会给当前操作的容器内的.item添加/移除类,完美解决你的问题!
内容的提问来源于stack exchange,提问作者Maxime Desrosiers
相关产品推荐
相关产品推荐

