React函数组件实现分类筛选按钮点击后高亮并定位对应区块
实现方案
核心交互可拆解为两个独立的逻辑模块:点击分类触发对应区块的平滑滚动、被选中的按钮保持高亮标识当前所处分类。
核心改造步骤
- 在父组件中新增当前选中分类的状态变量,作为按钮高亮的判断依据
- 给每个分类对应的内容区块配置唯一、与分类名规则绑定的
id属性,作为滚动定位的锚点 - 点击按钮的回调中,先更新选中状态,再通过原生DOM方法定位目标区块并触发平滑滚动
- 给处于选中状态的按钮追加自定义样式类,区分普通按钮的视觉效果
代码实现
1. 父组件逻辑(状态管理+滚动触发)
import { useState, useCallback } from 'react' function MenuContainer() { // 默认选中全部分类 const [activeCategory, setActiveCategory] = useState('全部') const categories = ['全部', '早餐', '午餐', '晚餐', '奶昔'] const handleCategoryClick = useCallback((selectedCategory) => { // 更新当前激活分类 setActiveCategory(selectedCategory) // 生成目标区块的匹配id:全部分类对应外层容器,其余分类统一转小写、空格替换为短横线 const targetId = selectedCategory === '全部' ? 'menu-content-wrapper' : selectedCategory.toLowerCase().replace(/\s+/g, '-') const targetElement = document.getElementById(targetId) if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }) } }, []) return ( <div> <Categories categories={categories} filter={handleCategoryClick} activeCategory={activeCategory} /> {/* 分类区块容器 */} <div id="menu-content-wrapper" className="menu-list"> <section id="breakfast" className="category-block"> <h3>早餐</h3> {/* 早餐菜品列表 */} </section> <section id="lunch" className="category-block"> <h3>午餐</h3> {/* 午餐菜品列表 */} </section> {/* 晚餐、奶昔区块按相同规则配置id即可 */} </div> </div> ) }
2. 改造后的Categories组件(支持高亮状态)
const Categories = ({ categories, filter, activeCategory }) => { return ( <div className="btn-container"> {categories.map((category, index) => { const isActive = category === activeCategory return ( <button type="button" className={`filter-btn ${isActive ? 'filter-btn--active' : ''}`} key={index} onClick={() => filter(category)} > {category} </button> ); })} </div> ); };
3. 配套样式配置
/* 按钮基础样式 */ .filter-btn { padding: 8px 16px; border: none; border-radius: 4px; background: transparent; color: #333; cursor: pointer; transition: all 0.2s ease; } /* 选中态按钮自定义样式,可根据设计调整背景、文字色 */ .filter-btn--active { background: #ff5722; color: #fff; } /* 基础平滑滚动配置 */ html { scroll-behavior: smooth; } /* 适配固定顶部导航的滚动偏移,数值与顶部导航高度保持一致即可 */ .category-block { scroll-margin-top: 80px; margin-top: 48px; }
注意事项
- 区块的id生成规则必须和点击时查找id的规则完全匹配,避免出现元素找不到、滚动失效的问题
- 当分类名称包含大写、空格时,统一通过规则转成小写短横线格式生成id,保证命名一致性
- 不需要引入额外的路由、滚动类第三方库,原生
scrollIntoView即可覆盖绝大多数平滑滚动场景 - 用
scroll-margin-top配置区块滚动偏移,比手动计算滚动位置稳定性更高,可适配不同高度的顶部固定导航
内容的提问来源于stack exchange,提问作者MasouD
相关产品推荐
相关产品推荐

