React Router如何在/:slug泛路径中排除new字符串实现路由匹配
实现方案
完全可以通过标准<Route />组件实现需求,核心利用Switch从上到下优先匹配精确路由的规则,写法如下:
方案1:分层路由写法(无正则,通用性最强)
父级/things路由对应的根组件
import { Switch, Route, useRouteMatch } from 'react-router-dom' import ComponentA from './ComponentA' import ComponentC from './ComponentC' export default function ThingsRoot() { const match = useRouteMatch() return ( <Switch> {/* 优先匹配单项目详情路由,匹配到直接渲染ComponentC,不渲染列表 */} <Route path={`${match.path}/:slug`} exact component={ComponentC} /> {/* 剩余路径统一渲染列表组件,列表内部处理新建模态框的路由 */} <Route path={match.path}> <ComponentA /> </Route> </Switch> ) }
ComponentA内部逻辑
import { Route, useRouteMatch } from 'react-router-dom' import ComponentB from './ComponentB' export default function ComponentA() { const match = useRouteMatch() return ( <div className="component-a"> {/* 此处为项目列表原有逻辑 */} <h2>项目列表</h2> {/* 匹配到新建路径时,叠加渲染模态框组件 */} <Route path={`${match.path}/new`} exact> <ComponentB /> </Route> </div> ) }
方案2:单文件路由+正则排除写法
如果不想分层写组件,也可以通过正则排除new作为slug的情况,在同一个组件内完成所有路由配置:
import { Switch, Route, useRouteMatch } from 'react-router-dom' import ComponentA from './ComponentA' import ComponentB from './ComponentB' import ComponentC from './ComponentC' export default function ThingsRoot() { const match = useRouteMatch() return ( <> <Switch> {/* 用正则排除slug为new的情况,只有slug不是new时才匹配详情页 */} <Route path={`${match.path}/:slug(?!new$)`} exact component={ComponentC} /> {/* 匹配列表页路由 */} <Route path={match.path} exact component={ComponentA} /> </Switch> {/* 新建路由独立写,匹配到时同时渲染B组件 */} <Route path={`${match.path}/new`} exact component={ComponentB} /> </> ) }
如果你需要按指定slug规则匹配
你之前的正则写法有误,React Router v5的路由参数正则不需要额外嵌套括号,匹配xxx-xxx-xxx-###格式的正确写法如下:
<Route path={`${match.path}/:slug(\\w+-\\w+-\\w+-\\d{3})`} exact component={ComponentC} />
该规则只会匹配符合格式的slug,不会命中/new路径。
内容的提问来源于stack exchange,提问作者Brett DeWoody
相关产品推荐
相关产品推荐

