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

如何让水平滚动纯JS代码作用于页面所有同类元素而非仅第一个?

解决多水平滚动区域的功能问题(纯JavaScript实现)

我完全懂你现在的处境——习惯了jQuery的写法,转纯JS时踩了几个典型小坑:比如只选中第一个滚动容器,还有不知道怎么精准操作触发事件的容器的子元素。咱们一步步来把这些问题搞定:

核心问题拆解

  1. 仅第一个滚动区域生效:原代码用document.querySelector('.items')只会抓取页面中第一个匹配的元素,后面的滚动容器根本没绑定事件,自然没法工作。
  2. 全局操作所有.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>

关键改动说明

  1. 选中所有滚动容器:用document.querySelectorAll('.items')获取页面中所有匹配的滚动容器,再通过forEach遍历,为每个容器单独绑定事件,确保每个区域都能独立工作。
  2. 精准操作当前容器的子元素:
    • 在mousedown事件中,用slider.querySelectorAll('.item')获取当前触发事件的容器下的所有.item子元素,这就对应了jQuery里$(this).children('.item')的逻辑(如果.item都是直接子元素,也可以用slider.children,但querySelectorAll支持更复杂的选择器,灵活性更高)。
    • 在mouseleave和mouseup事件中,同样只操作当前容器的子元素,移除noclick类,避免影响其他区域的元素交互。
  3. 独立状态变量:把isDown、startX、scrollLeft放在forEach的回调函数内部,让每个滚动容器都拥有自己的状态变量,不会出现多个容器状态互相干扰的问题。

这样修改后,每个.items区域都能独立实现点击拖动滚动,而且只会给当前操作的容器内的.item添加/移除类,完美解决你的问题!

内容的提问来源于stack exchange,提问作者Maxime Desrosiers

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:23:05