React Router第二种嵌套路由方案相对第一种的局限性探讨
先来看两种实现的代码:
官方推荐的嵌套路由方案
const App = () => ( <BrowserRouter> <div> <Route path="/tacos" component={Tacos}/> </div> </BrowserRouter> ) const Tacos = ({ match }) => ( <div> <Route path={match.url + '/carnitas'} component={Carnitas} /> </div> )
你的平级路由实现方案
const App = () => ( <BrowserRouter> <div> <Route path="/tacos" component={Tacos}/> <Route path={'tacos/carnitas'} component={Carnitas} /> </div> </BrowserRouter> ) const Tacos = ({ match }) => ( <div> </div> )
乍一看两种方案都能匹配/tacos/carnitas路径,但第二种平级写法其实有不少隐藏的局限性,咱们挨个拆解:
逻辑层级完全断裂,维护成本飙升
官方方案里,Carnitas是Tacos的子组件,完全贴合页面的逻辑——Carnitas就是tacos分类下的具体内容。但你把两个路由平级放在App里,相当于把父子关系硬生生拆开了。要是以后要给tacos加更多子路由(比如/tacos/al-pastor、/tacos/barbacoa),你得把所有这些路由都塞进App里,用不了多久App就会变成一个臃肿的路由垃圾堆,根本没法维护。硬编码路径,扩展性为零
官方用match.url拼接子路由路径的好处太明显了:要是哪天Tacos的父路径从/tacos改成/mexican-special/tacos,所有子路由会自动跟着更新,不用你手动改任何东西。但你的方案是硬写死'tacos/carnitas',一旦父路径变了,你得挨个修改所有关联的子路由,不仅麻烦,还很容易漏改导致页面404。渲染逻辑不符合嵌套页面的预期
当访问/tacos/carnitas时,你的方案会同时渲染Tacos和Carnitas两个组件(因为React Router的Route是匹配就渲染,除非加exact)。但正常场景下,我们希望子路由内容嵌套在父组件的布局里——比如Tacos里有个分类导航栏,Carnitas应该显示在导航栏下面。但你的写法里,Carnitas会和Tacos平级渲染在App的容器里,完全不是我们要的嵌套结构。要是给/tacos加exact,那访问子路由时Tacos就不渲染了,父布局直接消失,这更离谱。权限控制重复冗余,容易出错
要是以后需要给所有tacos相关的路由加权限(比如必须登录才能访问),官方方案只需要在Tacos组件里做一次校验,所有子路由都会自动继承这个权限。但你的方案得给每个平级的子路由都单独加权限逻辑,重复代码一大堆,还很容易出现有的路由加了权限,有的没加的情况,导致权限漏洞。
内容的提问来源于stack exchange,提问作者john

