Material-ui:路由选项卡使用尖锐 (#) 而不是斜杠 (/)

Material-ui: Routing tab using sharp(#) not slash(/)

我是 quiReact 的新手,我现在正在使用 ReactJS 和 material-ui 框架开发一个网站。

我的问题是如何自定义选项卡 link url 如 this site

在此站点上,当我切换选项卡按钮时,url 通过添加 #(a-custom-tab-link) 进行了更改。 假设我在 xxx/yyy url 上,如果我切换名称为 zzz 的选项卡,则 url 会更改为 xxx/yyy#zzz

我已经使用 material-ui 选项卡组件引用 material-ui tabs docs 创建了选项卡。 我可以使用 useRouteMatch 更改选项卡 url 并且代码示例是 here.

这是我的问题。

  1. 如何更改选项卡 url 不是通过添加 / 而是添加 # 就像 tab on this site
  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>
  ));

我们将不胜感激并提前致谢。

一段时间以来我一直在尝试做同样的事情,并且(几乎)成功了。我触发a URL片段写入window.location.hash,每当标签更改,在我的switchTabs回调(<Tabs onChange={switchTabs}>)中,并使用a window.addEventListner('hashchange', () => setTab(window.location.hash.slice(1)))事件更新带有 React 钩子的选项卡状态。一切正常,BackForward 按钮也有效。唯一的问题是服务器 看不到 URL 片段 (散列 (#) 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 片段纯粹是客户端。