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

使用forEach()时numberIncrease函数仅执行一次的JavaScript问题

问题原因
  • 核心问题出在numberIncrease()函数内部:每次调用它时,都会通过document.querySelector('.counter')重新获取元素,而这个方法只会返回匹配到的第一个元素——所以不管你在forEach里遍历多少个counter,函数始终只对第一个元素执行动画。
  • 另外,你在forEach循环中调用numberIncrease()时,没有把当前遍历到的counter元素传递给函数,导致函数根本不知道要针对哪个元素处理。
修复方案

不需要更换循环类型,只需要调整函数的参数传递和内部元素获取逻辑:

  1. 让numberIncrease()接收一个参数,代表要执行动画的目标元素
  2. 在forEach循环中调用函数时,传入当前遍历到的counter
  3. 移除函数内部document.querySelector('.counter')的代码,改用传入的参数
  4. 修正setCelebrateClass方法中引用的元素,确保操作的是当前目标元素
修改后的完整代码
<button id="button">test</button>
<h2 class="counter" data-count-start="500">788</h2>
<h2 class="counter" data-count-start="333">666</h2>

<script>
let test = true;
const button = document.getElementById('button');

button.addEventListener('click', function() {
  if (test) {
    document.querySelectorAll('.counter').forEach(counter => {
      numberIncrease(counter); // 传入当前遍历的元素
    })
  } else {
    console.log('no');
  }
})

// 接收目标元素作为参数
function numberIncrease(targetCounter) {
  const tl = gsap.timeline();
  const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

  animateCount(targetCounter); // 传递目标元素

  function animateCount(el) {
    const start = removeCommas(el.dataset.countStart);
    const end = removeCommas(el.textContent);

    tl.fromTo(
      el,
      {
        innerText: start,
        "--font-variation-weight": 300,
        scale: reducedMotion ? 1 : 0.99
      },
      {
        innerText: end,
        snap: { innerText: 1 },
        duration: reducedMotion ? 0 : 3,
        ease: "linear",
        onUpdate: () => {
          el.innerHTML = formatNumber(el.innerText);
        }
      }
    ).to(el, {
      scale: 1,
      "--font-variation-weight": 600,
      ease: "elastic.out(1, 0.2)",
      duration: 1.2
    });
  }

  function celebrate() {
    setCelebrateClass(true);
  }

  // 操作传入的目标元素
  function setCelebrateClass(enabled) {
    targetCounter.classList.toggle("celebrate", enabled);
  }

  function removeCommas(num) {
    return num.replace(/,/g, "");
  }

  function formatNumber(num) {
    return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
  }
}
</script>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 09:24:18