单页项目如何优雅的管理前端路径?

646 阅读2分钟

一个问题?

在 React 单页应用中,相信大家都会用到 react-router-dom 这个库,用来做路由管理,然而最后是不是都会写成下面这样呢?

<Switch>
  <Route path="/login" exact component={LoginPage} />
  <Route path="/notfound" exact component={NotFound} />
  <Route path="/notauth" exact component={NotAuth} />
  <Route path="/version/:collection/:book/:page/:version" exact component={VersionPage} />
  <Route path="/collection/:collection/books" exact breadcrumbName="" component={SpacePage} />
  <Route path="/collection/:collection/settings" exact breadcrumbName="" component={SettingPage} />
  <Route path="/collection/:collection/teams" exact breadcrumbName="" component={TeamsPage} />
  <Route path="/collection/:collection/recently" exact breadcrumbName="" component={RecentlyPage} />
  <Route path="/book/:id" exact component={BookLayout} />
  <Redirect from="/" exact to={DefaultFront} />
  <Redirect to="/notfound" />
</Switch>

所有的路由都写在一个文件里?随着路由越来越多,这个文件会越来越大。而且跳转页面是直接使用路径字符串,如 history.push('/login'),一旦我们想要修改一个页面的路径,就要在所有引用了这个路径的代码中修改。

有洁癖的同学应该和我感受相同,会觉得这真的 不 够 优 雅。那么可以怎样改善呢❓❓❓

第一步:将路径统一管理

第一步,我们可以将所有路径字符串统一管理。

// router/path.ts

// 不同模块的路径前缀
const pathPrefix = { 
  apply: '/application',
  intro: '/intro',
  console: '/console'
};

const paths = {
  login: '/login',
  home: '/',
  applyContainerInstance: pathPrefix.apply + '/container/instance',
  applyStorageFile: pathPrefix.apply + '/storage/file',
  introContainerInstance: pathPrefix.intro + '/container/instance',
  introStorageFile: pathPrefix.intro + '/storage/file',
  introDatabaseMySQL: pathPrefix.intro + '/database/mysql',
  consoleOverview: pathPrefix.console + '/overview',
  consoleInstance: pathPrefix.console + '/instance',
  consoleInstanceDetail: pathPrefix.console + '/instance/detail',
  consoleSG: pathPrefix.console + '/securityGroup',
  consoleSGCreate: pathPrefix.console + '/securityGroup/create',
  consoleSGDetail: pathPrefix.console + '/securityGroup/detail',
  consoleDockerAuth: pathPrefix.console + '/dockerAuth',
  consoleProjectMember: pathPrefix.console + '/projectMember'
};
​
export { pathPrefix, paths };

如上所示,我们将所有路径都统一写在 router/path.ts 文件中,并将它导出。这样,外部需要跳转某个页面时,写法就变成了这样:

import { paths } from '@/router/paths.ts'

//...
history.push(paths.login)

这样不仅显得清晰,而且如果我们想要改变路径名称,只需在 path.ts 中修改即可。

然而,这样也会存在一个问题,如果是 /project/:projectId 这样带有动态 id 的路径怎么办呢?这样的路径可以做路由匹配,可是不能直接用来跳转呀!不急,方法有两种。

  1. 替换

    import { paths } from '@/router/paths.ts'
    
    //...
    const projectPagePath = paths.project.replace(':projectId','1');
    history.push(projectPagePath)
    
  2. 使用 query

    除了 /project/:projectId 这种路径,我们也可以使用 /project?projectId=1 来携带动态 id。

    import { paths } from '@/router/paths.ts'
    
    //...
    history.push(`paths.project?projectId=${1}`)
    

第二步:分模块

前端页面往往是分模块的,这些模块路径的前缀都相同。举个例子,介绍页面 “/introduction/xxx”,管理页面“/admin/xxx”。我们可以把一个模块的路由单独维护在一个文件中,这样路由代码会更为清晰。

// router/index.tsx
const SwitchRouterComponent = () => {
  return (
    <Suspense fallback={<PageLoading />}>
      <Switch>
        <Route exact path={paths.login} component={Login} />
        <Route exact path={paths.home} component={Home} />
        <Route>
          <PageContainer>
            <Switch>
              {/* 前面导出路径时同时导出了路径前缀,是为了在这里使用,用来匹配一个模块 */}
              <Route path={pathPrefix.apply} component={Application} />   {/* application 模块 */}
              <Route path={pathPrefix.intro} component={Intro} />  {/* introduction 模块 */}
              <Route path={pathPrefix.console} component={Console} /> {/* console 模块 */}
              <Route path="*" component={NotFound} />
            </Switch>
          </PageContainer>
        </Route>
      </Switch>
    </Suspense>
  );
};

模块路由的代码如下:

// router/intro.tsx 
// introduction 模块
const Intro = () => {
  return (
    <Switch>
      <Route exact path={paths.introContainerInstance} component={Instance} />
      <Route exact path={paths.introStorageFile} component={File} />
      <Route exact path={paths.introDatabaseMySQL} component={Database} />
      <Redirect to={paths.introContainerInstance} />
    </Switch>
  );
};

把不同模块的路由维护在不同文件中,这样管理起来就方便多了,而且不用将所有路由都堆在一个文件中。

总结

对于大的后台管理项目,我觉得这样去管理路由路径还是很有必要的,方便修改,而且不会显得乱!!然而对于小项目,页面数量很少,就没有这样做的必要了~

最后,如果大家有什么其他好的做法,欢迎评论交流~😺