最近在学习react,在路由这一块有点看不懂,第一感觉是灵活性很大,想怎么来就怎么来,但问题也来了,稍微复杂一点就GG了,不如vue的傻瓜式配置来的方便。

先说一下vue的路由配置方式,目录结构如下(简化了结构)

━ src
  ├━ App.vue
  ├━ layout.vue
  ├━ router.js
  ┕━ main.js

main.js的内容是官方标配,没什么好说的,引入路由配置并加载

import router from './router'  // 引入路由配置
import App from './App.vue'
new Vue({
  router, // 加载路由配置
  render: h => h(App)
}).$mount('#app')

App.vue中添加一个router-view作为一级路由视图

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

router.js书写路由配置

import Layout from './layout'
export default new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      component: Layout,
      children: [
        {
          path: 'about',
          component: () => import('./About.vue')
        },
        {
          path: 'about2',
          component: () => import('./About2.vue')
        }
      ]
    },
    {
      path: '/404',
      name: '404',
      component: () => import('./404.vue')
    }
  ]
})

layout.vue布局文件,中间添加一个router-view作为二级路由视图

<template>
  <div class="layout-container">
    <header>
      <router-link to="/">Home</router-link>
      <router-link to="/about">About</router-link>
      <router-link to="/about2">About2</router-link>
      <router-link to="/404">404</router-link>
    </header>
    <router-view class="layout-content"></router-view>
    <footer></footer>
  </div>
</template>

简单的说一下,
App.vue就是根元素,路径//404都将对应路由的组件渲染在App中的router-view位置,分别是layout.vue404.vue
路径/下的子路由aboutabout2对应的完整路径分别为/about/about2,当匹配这两个路径时,首先会在App根元素下渲染一级路由的组件,即layout.vue,然后再在一级路由组件(layout.vue)中的router-view位置渲染二级路由组件。

现在来看一下react-router的工作方式,一个简单的路由如下(用的是react-router-dom,)
修改App.js,使用了Switch包裹,表示只渲染第一个匹配路由的组件

import React from 'react';
import { BrowserRouter, Route, Link } from "react-router-dom";

const Layout = props => (
  <div className="layout-container">
    <header>
      <Link to='/'>Home</Link>
      <Link to='/about'>About</Link>
      <Link to='/about2'>About2</Link>
      <Link to='/404'>404</Link>
    </header>
    {props.children}
    <footer></footer>
  </div>
)
const About = props => (
  <div>this is About Page</div>
)
const About2 = props => (
  <div>this is About2 Page</div>
)
const Page404 = props => (
  <div>this is 404 Page <Link to="/">GO HOME</Link></div>
)

const App = props => (
  <BrowserRouter>
    <Switch>
      <Route path='/404' component={Page404}></Route>
      <Layout>
        <Route path="about" component={About}></Route>
      </Layout>
    </Switch>
  </BrowserRouter>
)
export default App;

对比vue,react-router一个很明显的区别就是路由是直接写在组件中的,这继承了react的核心思想,一切皆为组件。

其实仔细想想,从感官层面来讲,vue-router中的router-view也是一个特殊的组件,功能有点类似vue的动态组件<component />,通过匹配地址与路由,将对应的组件替渲染出来;react-router也是如此,有了Switch,react-router将匹配到的唯一路由对应的组件渲染出来,这样一想,两者其实很相似,区别在于vue将这一过程在内部封装简化了,而react则显式的需要我们手动去书写这一过程。

调试react-router可以发现,在404页面和home页面之间切换,页面时发生变化了的,说明路由生效,但是点击about页面无任何变化,这就有点惆怅了,难道不支持嵌套路由???

其实并不是,如果把404路由放到Layout下面去的话(如下更改,下面简称代码2,原来的简称代码1),会发现404页面也无法切换了

// 代码2
const App = props => (
  <BrowserRouter>
    <Switch>
      <Layout>
        <Route path="about" component={About}></Route>
      </Layout>
      <Route path='/404' component={Page404}></Route>
    </Switch>
  </BrowserRouter>
)

这是因为使用了Switch,它只会渲染第一个匹配的组件,那么代码2中不管匹配到什么地址,Switch在渲染了Layout后就不在渲染其他的路由对应的组件了,那么加一层路由地址呢???(如下代码3)

const App = props => (
  <BrowserRouter>
    <Switch>
      <Route path='/'>
        <Layout>
          <Route path='about' component={About}></Route>
        </Layout>
      </Route>
      <Route path='/404' component={Page404}></Route>
    </Switch>
  </BrowserRouter>

结果还是不起作用,通过react-dev-tool发现,内部的路由组件根本没有发生变化,其实到这里问题就已经很明显了,加上之前的分析,react复杂路由之所以不生效就是因为路由匹配问题,不管是/404还是/about,在代码3这种写法下,路由匹配到<Route path='/'>这里的时候就截至了,不会再往下或往后继续匹配,这让我想起了ThinkPHP的路由,需要将静态路由和长路由写在前面,或者添加截至符号。react-router可以通过Routeexact属性来达到完全匹配的效果。代码修改如下(代码4)

const App = props => (
  <BrowserRouter>
    <Switch>
      <Route exact path='/' component={Layout}></Route>
      <Route path='/404' component={Page404}></Route>
      <Layout>
        <Route path='/about' component={About}></Route>
        <Route path='/about2' component={About2}></Route>
      </Layout>
    </Switch>
  </BrowserRouter>
)

代码4可以实现4个页面的切换,效果和vue一致。

总结:react的路由配置和vue相比,还是有很大区别的,vue的嵌套路由比较直观,书写也很方便,react的路由配置更贴近于传统的路由配置方式。官方倒是有嵌套路由的案例,但是那个还没有弄懂,代码调试不通过,我看的那个应该是旧版的文档,可能不适用新版的react-router。

Logo

前往低代码交流专区

更多推荐