Files
file-templates/ui components/sticknav/StickyNavExample.jsx

128 lines
3.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState, useEffect, useRef } from 'react';
import './StickyNavExample.css';
/**
* 最小化示例:实现滚动吸顶与分类高亮效果
*/
const StickyNavExample = () => {
// 分类数据
const categories = [
{ id: 'section1', name: '分类一' },
{ id: 'section2', name: '分类二' },
{ id: 'section3', name: '分类三' },
{ id: 'section4', name: '分类四' },
];
// 状态管理
const [activeSection, setActiveSection] = useState(categories[0].id);
const isManualScrollRef = useRef(false);
const timerRef = useRef(null);
// 监听滚动事件,更新当前活动分类
useEffect(() => {
const handleScroll = () => {
// 如果是手动点击导致的滚动,则跳过自动检测
if (isManualScrollRef.current) return;
const stickyNav = document.querySelector('.sticky-nav');
const stickyHeight = stickyNav?.getBoundingClientRect().height || 0;
const triggerOffset = stickyHeight + 20; // 触发点位置
// 遍历所有分类区块,检查哪个在视口中
categories.forEach(category => {
const section = document.getElementById(category.id);
if (section) {
const rect = section.getBoundingClientRect();
// 当区块顶部进入触发点时,将其设为当前活动分类
if (rect.top <= triggerOffset && rect.bottom >= triggerOffset) {
setActiveSection(category.id);
}
}
});
};
// 添加滚动事件监听
window.addEventListener('scroll', handleScroll);
// 组件卸载时移除事件监听
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// 处理分类点击事件
const handleCategoryClick = (categoryId) => {
// 清除之前的定时器
if (timerRef.current) {
clearTimeout(timerRef.current);
}
// 设置为手动滚动,暂时禁用自动检测
isManualScrollRef.current = true;
setActiveSection(categoryId);
// 滚动到对应区块
const section = document.getElementById(categoryId);
const stickyNav = document.querySelector('.sticky-nav');
if (section && stickyNav) {
const stickyHeight = stickyNav.getBoundingClientRect().height;
const sectionTop = section.offsetTop - stickyHeight;
window.scrollTo({
top: sectionTop,
behavior: 'smooth'
});
}
// 设置定时器1秒后重新启用滚动检测
timerRef.current = setTimeout(() => {
isManualScrollRef.current = false;
}, 1000);
};
return (
<div className="container">
{/* 页面标题 */}
<h1 className="title">滚动吸顶示例</h1>
<p className="subtitle">向下滚动查看效果</p>
{/* 粘性导航区域 */}
<div className="sticky-nav">
{/* 搜索框 */}
<input
type="text"
className="search-box"
placeholder="搜索..."
/>
{/* 分类标签 */}
<div className="category-tabs">
{categories.map(category => (
<button
key={category.id}
className={activeSection === category.id ? 'active' : ''}
onClick={() => handleCategoryClick(category.id)}
>
{category.name}
</button>
))}
</div>
</div>
{/* 内容区域 */}
{categories.map(category => (
<div
key={category.id}
id={category.id}
className="content-section"
>
<h2>{category.name}</h2>
<p>这是{category.name}的内容区域滚动时当此区域进入视口中间位置对应的分类标签会自动高亮</p>
{/* 添加一些占位内容使页面可滚动 */}
<div className="placeholder"></div>
</div>
))}
</div>
);
};
export default StickyNavExample;