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

实现带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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 08:54:02