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

如何通过HTTP路径设置MUI Tabs组件的激活标签

实现方案

整体不需要改动原有Tabs组件的交互逻辑,只需结合React Router的路径参数做状态同步即可,步骤如下:

1. 路由配置

首先在路由规则中给标签页路由配置可选的动态参数,示例(React Router v6):

{
  path: '/tabs/:tabSlug?',
  element: <VerticalTabs />
}

参数末尾的?表示可选,访问/tabs时默认激活第一个标签。

2. 改造VerticalTabs组件

核心逻辑

  • 定义路径slug和标签索引的映射关系
  • 从路由参数中读取slug,匹配对应标签索引作为激活状态初始值
  • 监听路由参数变化,同步更新激活标签
  • 切换标签时主动修改路由路径

完整修改后代码

import * as React from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';

// 标签slug和索引的映射关系,可根据业务调整
const tabSlugMap = {
  0: 'one',
  1: 'two',
  2: 'three',
  3: 'four',
  4: 'five',
  5: 'six',
  6: 'seven'
} as const;
const slugToIndexMap = Object.fromEntries(
  Object.entries(tabSlugMap).map(([idx, slug]) => [slug, Number(idx)])
);

interface TabPanelProps {
  children?: React.ReactNode;
  index: number;
  value: number;
}

function TabPanel(props: TabPanelProps) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`vertical-tabpanel-${index}`}
      aria-labelledby={`vertical-tab-${index}`}
      {...other}
    >
      {value === index && (
        <Box sx={{ p: 3 }}>
          <Typography>{children}</Typography>
        </Box>
      )}
    </div>
  );
}

function a11yProps(index: number) {
  return {
    id: `vertical-tab-${index}`,
    'aria-controls': `vertical-tabpanel-${index}`,
  };
}

export default function VerticalTabs() {
  const { tabSlug } = useParams();
  const navigate = useNavigate();
  const [value, setValue] = React.useState(() => {
    // 初始化时从路由参数匹配激活标签,无匹配则默认第一个
    return slugToIndexMap[tabSlug as string] ?? 0;
  });

  // 监听路由参数变化,同步更新激活标签
  React.useEffect(() => {
    const targetIndex = slugToIndexMap[tabSlug as string] ?? 0;
    setValue(targetIndex);
  }, [tabSlug]);

  const handleChange = (event: React.SyntheticEvent, newValue: number) => {
    setValue(newValue);
    // 切换标签时更新路由路径
    navigate(`/tabs/${tabSlugMap[newValue]}`);
  };

  return (
    <Box
      sx={{ flexGrow: 1, bgcolor: 'background.paper', display: 'flex', height: 224 }}
    >
      <Tabs
        orientation="vertical"
        variant="scrollable"
        value={value}
        onChange={handleChange}
        aria-label="Vertical tabs example"
        sx={{ borderRight: 1, borderColor: 'divider' }}
      >
        <Tab label="Item One" {...a11yProps(0)} />
        <Tab label="Item Two" {...a11yProps(1)} />
        <Tab label="Item Three" {...a11yProps(2)} />
        <Tab label="Item Four" {...a11yProps(3)} />
        <Tab label="Item Five" {...a11yProps(4)} />
        <Tab label="Item Six" {...a11yProps(5)} />
        <Tab label="Item Seven" {...a11yProps(6)} />
      </Tabs>
      <TabPanel value={value} index={0}>
        Item One
      </TabPanel>
      <TabPanel value={value} index={1}>
        Item Two
      </TabPanel>
      <TabPanel value={value} index={2}>
        Item Three
      </TabPanel>
      <TabPanel value={value} index={3}>
        Item Four
      </TabPanel>
      <TabPanel value={value} index={4}>
        Item Five
      </TabPanel>
      <TabPanel value={value} index={5}>
        Item Six
      </TabPanel>
      <TabPanel value={value} index={6}>
        Item Seven
      </TabPanel>
    </Box>
  );
}

优化建议

如果标签数量多或者后续会频繁调整,可以把标签配置抽成统一数组,遍历渲染标签和面板,避免手动维护映射关系:

const tabConfig = [
  { label: 'Item One', slug: 'one', content: 'Item One' },
  { label: 'Item Two', slug: 'two', content: 'Item Two' },
  // 剩余标签配置
]
// 渲染Tab时直接遍历tabConfig.map((item, idx) => <Tab label={item.label} {...a11yProps(idx)} />)
// 渲染TabPanel同理遍历即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:39:03