实现带Material-UI风格底部选项卡且支持左右点击切换的滑块组件
基于Material UI基础Tabs的底部滑块Tab实现方案
实现思路
- 整体结构对齐Material UI原生Tabs的布局逻辑:上方为内容展示区,下方为Tab导航栏,导航栏的选中指示条直接复用组件自带的动画能力,无需自定义计算位置
- 替换原Bootstrap实现中垂直方向的slideUp/slideDown切换逻辑,改为水平方向的内容轨道位移,匹配示例图的滑块滑动效果
- 左右切换按钮通过修改当前选中Tab的索引值,联动内容轨道做对应方向的位移,实现无跳转的即时切换
具体实现代码
import { useState } from 'react'; import { Tabs, Tab, IconButton } from '@mui/material'; import { ArrowBack, ArrowForward } from '@mui/icons-material'; export default function SliderTabs() { // 记录当前选中的Tab索引 const [activeIndex, setActiveIndex] = useState(0); // Tab配置项 const tabConfig = [ { key: 'mowers', label: 'Mowers' }, { key: 'jewelry', label: 'Jewelry' }, { key: 'cleaner', label: 'Cleaner' }, { key: 'watch', label: 'Watch' } ]; // Tab切换联动 const handleTabSwitch = (_, newIndex) => { setActiveIndex(newIndex); }; // 左侧按钮切换上一个Tab const handlePrev = () => { setActiveIndex(current => Math.max(0, current - 1)); }; // 右侧按钮切换下一个Tab const handleNext = () => { setActiveIndex(current => Math.min(tabConfig.length - 1, current + 1)); }; return ( <div className="slider-tab-wrapper"> {/* 内容滑块区域 */} <div className="content-slider" style={{ position: 'relative', overflow: 'hidden' }}> <div className="slider-track" style={{ display: 'flex', transform: `translateX(-${activeIndex * 100}%)`, transition: 'transform 0.3s cubic-bezier(0.4, 0, 0.2, 1)' }} > {/* 渲染每个Tab的内容 */} {tabConfig.map(item => ( <div key={item.key} className="tab-pane" style={{ flex: '0 0 100%', minHeight: '320px' }} > {/* 这里放置每个Tab对应的页面内容 */} </div> ))} </div> {/* 左右切换触发按钮 */} <IconButton onClick={handlePrev} disabled={activeIndex === 0} style={{ position: 'absolute', left: 12, top: '50%', transform: 'translateY(-50%)' }} > <ArrowBack /> </IconButton> <IconButton onClick={handleNext} disabled={activeIndex === tabConfig.length - 1} style={{ position: 'absolute', right: 12, top: '50%', transform: 'translateY(-50%)' }} > <ArrowForward /> </IconButton> </div> {/* 底部Material UI原生Tab导航 */} <Tabs value={activeIndex} onChange={handleTabSwitch} variant="fullWidth" indicatorColor="primary" > {tabConfig.map(item => <Tab key={item.key} label={item.label} />)} </Tabs> </div> ); }
关键优化细节
- 内容滑块的动画缓动曲线和Material UI Tabs的指示条动画保持完全一致,避免两个组件动画不同步产生的割裂感
- 当滑块滑动到第一个/最后一个Tab时,对应方向的切换按钮自动置灰,禁止无效点击
- 移除原jQuery实现中逐个控制Tab pane显示隐藏的逻辑,所有内容统一放在横向轨道上,靠外层容器裁切实现切换,彻底解决切换时页面高度跳动的问题
- 切换按钮的逻辑直接操作选中Tab的状态值,不触发额外的DOM操作,性能比原生jQuery实现提升明显
内容的提问来源于stack exchange,提问作者Sylvester
相关产品推荐
相关产品推荐

