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

React中重复if判断与DOM选择器代码的优化方案咨询

React中重复if判断与DOM选择器代码的优化方案咨询

嘿,这段代码的重复问题一眼就能看出来,咱们完全可以通过抽象重复逻辑的方式来简化它,不仅能让代码更清爽,以后再加类似的滚动触发效果也会方便很多!

先说说原代码的问题

你现在的代码里,每个区块(Prices/Contact/Moreinfo)都在做几乎一模一样的操作:重复调用document.querySelector查询DOM、重复写相同的条件判断、重复执行样式和类名的操作。这样不仅冗余,以后要修改判断条件或者样式时,得改好几处,很容易出错。

优化后的代码方案

咱们可以用React的useRef缓存DOM元素,再把重复逻辑抽成循环处理的方式,同时还能修复原代码里没清理滚动监听的内存泄漏问题:

import { useEffect, useRef } from 'react';

function YourComponent() {
  // 用useRef缓存所有需要操作的DOM元素,避免重复查询
  const pricesSectionRef = useRef(null);
  const pricesArrRef = useRef(null);
  const contactSectionRef = useRef(null);
  const contactRef = useRef(null);
  const moreinfoSectionRef = useRef(null);
  const moreinfoRef = useRef(null);

  useEffect(() => {
    // 把每个区块的配置统一放到数组里,方便管理和扩展
    const scrollTriggerConfigs = [
      {
        sectionRef: pricesSectionRef,
        targetElementRef: pricesArrRef,
        animationClass: 'pricesArrAnim'
      },
      {
        sectionRef: contactSectionRef,
        targetElementRef: contactRef,
        animationClass: 'contactAnim'
      },
      {
        sectionRef: moreinfoSectionRef,
        targetElementRef: moreinfoRef,
        animationClass: 'moreinfoAnim'
      }
    ];

    // 抽象滚动处理的核心逻辑
    const handleScroll = () => {
      scrollTriggerConfigs.forEach(config => {
        // 先判断元素是否存在,避免组件未挂载时出现null报错
        if (!config.sectionRef.current || !config.targetElementRef.current) return;

        const sectionTop = config.sectionRef.current.getBoundingClientRect().top;
        const targetElement = config.targetElementRef.current;

        if (sectionTop === 78) {
          targetElement.style.opacity = '1';
          targetElement.classList.add(config.animationClass);
        } else if (sectionTop > 660) {
          targetElement.style.opacity = '0';
          targetElement.classList.remove(config.animationClass);
        }
      });
    };

    // 添加滚动监听
    document.addEventListener('scroll', handleScroll);

    // 清理函数:组件卸载时移除监听,防止内存泄漏
    return () => {
      document.removeEventListener('scroll', handleScroll);
    };
  }, []); // 空依赖数组,确保监听只挂载一次

  return (
    <div>
      {/* 给对应的元素绑定ref */}
      <div id="prices" ref={pricesSectionRef}>...</div>
      <div className="pricesArr" ref={pricesArrRef}>...</div>

      <div id="contact" ref={contactSectionRef}>...</div>
      <div className="contact" ref={contactRef}>...</div>

      <div id="moreinfo" ref={moreinfoSectionRef}>...</div>
      <div className="moreinfo" ref={moreinfoRef}>...</div>
    </div>
  );
}

额外的优化小建议

如果想让样式和代码彻底分离,你可以把opacity的控制也改成CSS类的方式:

/* 定义通用的可见性类 */
.section-visible {
  opacity: 1;
}

/* 保留你的动画类 */
.pricesArrAnim {
  /* 你的动画样式 */
}

然后把代码里的样式操作改成类名操作:

if (sectionTop === 78) {
  targetElement.classList.add('section-visible', config.animationClass);
} else if (sectionTop > 660) {
  targetElement.classList.remove('section-visible', config.animationClass);
}

这样就不用直接操作DOM样式了,更符合React的最佳实践,也方便后续修改样式。

备注:内容来源于stack exchange,提问作者Jesús Fernández

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:24:51