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

如何用TypeScript实现React头部导航栏吸顶效果?

导航栏吸顶问题修复方案

1. 修正Sticky组件的Props接收逻辑

你的Sticky组件在props处理上存在两处核心错误:一是错误解构了props参数,二是子元素属性名不符合React规范。同时缺少初始滚动状态检测,导致页面刷新时已滚动的场景无法触发吸顶。

修改sticky.tsx:

import React, { useState, useEffect, useRef } from 'react';
import './Sticky.scss';

interface StickyProps {
    children: React.ReactNode, // 改用React内置的children属性
    top: number,
}

// 正确解构props对象
const Sticky: React.FunctionComponent<StickyProps> = ({ children, top }) => {
  const [isSticky, setSticky] = useState(false);
  const ref = useRef<HTMLDivElement>(null); // 添加强类型定义

  useEffect(() => {
    handleScroll(); // 初始调用,处理页面刷新时已滚动的情况
    window.addEventListener('scroll', handleScroll);
    // 移除监听时直接传原函数,避免创建新函数导致无法解绑
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, [top]); // 依赖top参数,值变化时重新绑定监听

  const handleScroll = () => {
    if (ref.current) {
      const rect = ref.current.getBoundingClientRect();
      setSticky(rect.top <= top);
    }
  };

  return (
      <div className={`sticky__wrapper ${isSticky ? 'sticky' : ''}`} ref={ref}>
        <div className="sticky--inner">
            {children}
        </div>
      </div>
  );
};

export default Sticky

2. 完善Sticky组件的CSS样式

原CSS中核心定位属性被注释,且缺少吸顶后的基础样式,导致视觉上无变化。同时需要处理页面跳动问题。

修改sticky.scss:

.sticky__wrapper {
    position: relative;
    /* 设置与导航栏一致的最小高度,避免吸顶时页面跳动 */
    min-height: 88px;
    box-sizing: border-box;
  }
  
.sticky .sticky--inner {
    position: fixed;
    top: 0; /* 取消注释,固定到顶部 */
    left: 0;
    right: 0;
    z-index: 999; /* 提高层级避免被遮挡 */
    background-color: #fff; /* 添加背景色防止内容穿透 */
    box-shadow: 0 2px 8px rgba(0,0,0,0.1); /* 可选:添加阴影增强层次感 */
}

3. 调整Header组件的适配样式

确保导航栏在吸顶时能铺满宽度,避免内边距导致布局错位。

修改index.tsx中的HeaderSection:

export const HeaderSection = styled("header")`
  padding: 1rem 0.5rem;
  width: 100%;
  box-sizing: border-box; /* 内边距不影响宽度计算 */

  .ant-row-space-between {
    align-items: center;
    text-align: center;
  }
`;

4. 正确调用Sticky组件

确保在父组件中正确导入并使用,示例:

import Sticky from './Sticky';
import Header from './Header';

// 页面中使用
<Sticky top={0}>
  <Header />
</Sticky>

额外性能优化建议

滚动事件会频繁触发,添加防抖处理可以降低性能消耗:

// 自定义防抖函数
const debounce = (func: Function, delay: number) => {
  let timer: NodeJS.Timeout;
  return (...args: any[]) => {
    clearTimeout(timer);
    timer = setTimeout(() => func(...args), delay);
  };
};

// 在Sticky组件内部替换handleScroll
const debouncedHandleScroll = React.useMemo(() => debounce(handleScroll, 100), [top]);

// useEffect中使用防抖后的函数
useEffect(() => {
  handleScroll();
  window.addEventListener('scroll', debouncedHandleScroll);
  return () => {
    window.removeEventListener('scroll', debouncedHandleScroll);
  };
}, [debouncedHandleScroll]);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:05:17