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

如何在React页面中不使用jQuery实现滚动切换Logo等元素颜色?

当然有办法!完全不用jQuery,用React本身的API就能轻松实现这个滚动切换元素样式的效果。下面我给你一步步拆解实现思路和代码示例:

核心思路

通过监听浏览器的滚动事件,判断当前滚动位置对应的页面板块,然后切换全局或局部的主题状态,最终让Logo和其他元素根据状态更新样式。整个过程完全基于React Hooks和原生JavaScript,不需要依赖任何第三方库。

具体实现步骤

1. 基础版:监听滚动+状态切换

这是最直接的实现方式,适合板块划分清晰的场景:

import { useState, useEffect, useRef } from 'react';

function ScrollThemeSwitch() {
  // 用状态保存当前主题模式(浅色/深色)
  const [isDarkMode, setIsDarkMode] = useState(false);
  // 用ref标记需要触发切换的板块位置
  const targetSectionRef = useRef(null);

  useEffect(() => {
    const handleScroll = () => {
      const scrollPosition = window.scrollY;
      // 获取目标板块的顶部偏移量(可以根据需求调整触发阈值)
      const targetOffset = targetSectionRef.current?.offsetTop - 80 || 0;

      // 当滚动到目标位置时切换主题
      if (scrollPosition >= targetOffset) {
        setIsDarkMode(true);
      } else {
        setIsDarkMode(false);
      }
    };

    // 挂载时添加滚动监听
    window.addEventListener('scroll', handleScroll);
    // 卸载时移除监听,避免内存泄漏
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  return (
    <div className={`app-wrapper ${isDarkMode ? 'dark-mode' : 'light-mode'}`}>
      {/* Logo根据主题切换样式 */}
      <div className={`site-logo ${isDarkMode ? 'logo-dark' : 'logo-light'}`}>
        {/* 这里可以是图片或文字Logo */}
        MyBrand
      </div>

      {/* 第一个浅色板块 */}
      <section className="section light-section">
        首页内容区
      </section>
      {/* 触发主题切换的板块 */}
      <section ref={targetSectionRef} className="section dark-section">
        深色内容区
      </section>
      {/* 后续板块 */}
      <section className="section light-section">
        更多内容
      </section>
    </div>
  );
}

export default ScrollThemeSwitch;

搭配对应的CSS样式:

.app-wrapper {
  transition: background-color 0.3s ease;
}

.light-mode {
  background-color: #ffffff;
}

.dark-mode {
  background-color: #121212;
}

.site-logo {
  position: fixed;
  top: 20px;
  left: 20px;
  font-size: 28px;
  font-weight: bold;
  transition: color 0.3s ease;
}

.logo-light {
  color: #121212;
}

.logo-dark {
  color: #ffffff;
}

.section {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
}

.light-section {
  background-color: #ffffff;
  color: #121212;
}

.dark-section {
  background-color: #121212;
  color: #ffffff;
}

2. 优化版:节流函数+Intersection Observer

如果页面板块较多,或者想要更流畅的性能,可以做两个优化:

  • 给滚动事件加节流,减少触发频率
  • 使用Intersection Observer API,监听板块是否进入视口(比监听scroll更高效)

节流函数实现

// 简单的自定义节流函数
const throttle = (func, delay) => {
  let lastTriggerTime = 0;
  return (...args) => {
    const now = Date.now();
    if (now - lastTriggerTime >= delay) {
      func(...args);
      lastTriggerTime = now;
    }
  };
};

// 在useEffect中替换原handleScroll
const throttledScrollHandler = throttle(handleScroll, 100);
window.addEventListener('scroll', throttledScrollHandler);
return () => window.removeEventListener('scroll', throttledScrollHandler);

Intersection Observer 实现

useEffect(() => {
  // 创建观察者实例
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      // 当板块进入视口50%时切换主题
      if (entry.isIntersecting) {
        const theme = entry.target.dataset.theme;
        setIsDarkMode(theme === 'dark');
      }
    });
  }, { threshold: 0.5 });

  // 监听所有带data-theme属性的板块
  document.querySelectorAll('[data-theme]').forEach(section => {
    observer.observe(section);
  });

  return () => observer.disconnect();
}, []);

对应的板块要添加data-theme属性:

<section className="section light-section" data-theme="light">
  首页内容区
</section>
<section className="section dark-section" data-theme="dark">
  深色内容区
</section>
总结

这些方案都是纯React+原生JavaScript实现,完全不需要jQuery,而且可以根据你的页面结构灵活调整触发条件和样式变化逻辑。如果有多个主题切换点,只需要扩展状态判断逻辑即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:32:36