首页 > 解决方案 > Material-ui:使用尖锐(#)而不是斜杠(/)的路由选项卡

问题描述

我对 React 很陌生,我现在正在使用 ReactJS 和 material-ui 框架开发一个站点。

我的问题是如何像这个网站一样自定义标签链接网址

在这个网站上,当我切换选项卡按钮 url 时,添加#(a-custom-tab-link). 假设我在xxx/yyyurl 上,如果我切换名为 zzz 的选项卡,则 url 更改为xxx/yyy#zzz.

我已经使用引用material-ui tabs docs 的material-ui tabs 组件制作了标签。而且我可以使用更改标签网址useRouteMatch,代码示例在这里

这是我的问题。

  1. 如何更改标签网址不是通过添加/而是在本网站上#添加类似标签
  2. 如何将第一个选项卡的路由器设置为与其父路由器相同,以便自动显示。(我这样做没有考虑路由器,但如果我考虑在选项卡切换上更改路由器,我不能这样做)

这是我目前的代码片段。

  var TabHeaders = tabs.map((tab, index) => (
    <Tab
      key={index.toString()}
      component={Link}
      to={`${match.url}/${tab.label}`}
      label={tab["label"]}
      {...a11yProps(tab["index"])}
    />
  ));

  var TabContents = tabs.map((tab, index) => (
    <Route key={tab.id} exact path={`${match.url}/${tab.label}`}>
      <TabPanel value={value} index={tab["index"]}>
        {tab["children"]}
      </TabPanel>
    </Route>
  ));

并且简单地将 / 更改为 # 不能像下面这样工作。

  var TabHeaders = tabs.map((tab, index) => (
    <Tab
      key={index.toString()}
      component={Link}
      to={`${match.url}#${tab.label}`}
      label={tab["label"]}
      {...a11yProps(tab["index"])}
    />
  ));

  var TabContents = tabs.map((tab, index) => (
    <Route key={tab.id} exact path={`${match.url}#${tab.label}`}>
      <TabPanel value={value} index={tab["index"]}>
        {tab["children"]}
      </TabPanel>
    </Route>
  ));

任何帮助将不胜感激,并提前感谢。

标签: reactjsroutestabsreact-router-dom

解决方案


一段时间以来,我一直在尝试做同样的事情,并且(几乎)可以正常工作。window.location.hash每当标签发生变化时,我都会在switchTabs回调 ( ) 中触发 URL 片段写入<Tabs onChange={switchTabs}>,并使用window.addEventListner('hashchange', () => setTab(window.location.hash.slice(1)))事件通过 React 钩子更新标签状态。所有这些都很好,BackForward按钮也可以。唯一的问题是服务器看不到 URL 片段(URL 的哈希#(页面加载后必须重新渲染。那是我卡住的部分。如果您不使用服务器端渲染,这可能不是问题,您可以这样做

const [currentTab, setTab] = useState(window.location.hash.slice(1) || 'myDefaultTab')
const switchTabs = (_, newTab) => {
  if (window.loaction.hash !== `#${newTab}`)
    window.location.hash = `#${newTab}`
  setTab(newTab)
}
window.addEventListner('hashchange', () => {
  setTab(window.location.hash.slice(1))
})
// ... then in your <Tabs> component
<Tabs value={currentTab} onChange={switchTabs}>
  // ...
</Tabs>

我决定改为使用对服务器可见的 URL 样式,以便可以将初始useState值设置为 URL 查询参数。我使用的 Insetead ?tab=myTabName,在使用服务器端渲染时效果更好。如果您有兴趣:

// ... in render function: (initialTab is from the server query params)
const [currentTab, setTab] = useState(initialTab)
const switchTab = (_, newTab: string) => {
    setTab(newTab)
    if (typeof window !== 'undefined')
        window.history.pushState(null, null, `?tab=${newTab}`)
}
if (typeof window !== 'undefined') {
    window.addEventListener('popstate', () => {
        const params = new URLSearchParams(window.location.search)
        const newTab = params.get('tab')
        if (newTab) setTab(newTab)
    });
}

这完美地工作,导航按钮(历史),链接,刷新等。这不使用Router或任何东西,并且非常基本,但话又说回来,#URL片段纯粹是客户端。


推荐阅读