前言

前端路由的作用就是将单页应用的状态处理成多页路由的样子,react 和 vue 的路由是一样的,一个地址对应一个组件,下面看看 react-router 的用法

安装

在 vue 中想要使用 router 需要进行安装,react 一样也需要安装

目前 react-router 全称为 react-router-dom ,当前最新版是 6

安装指令如下

npm i react-router-dom@6

Link

接下来实现一个效果,点击首页展示首页这个页面内容,点击关于页展示关于这个页面内容

5 分钟掌握 react 中的 router_Layout

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

const Home = () => <div>this is home</div>

const About = () => <div>this is about</div>

const App = () => {
    return (
        <div className='app'>
            <BrowserRouter>
                <Link to='/'>首页 | </Link>
                <Link to='about'>关于</Link>

                <Routes>
                    <Route path='/' element={<Home />}></Route>
                    <Route path='/about' element={<About />}></Route>
                </Routes>
            </BrowserRouter>
        </div>
    );
};

export default App;

直接在根组件中写两个页面出来,路由的写法需要用 BrowserRouter 进行包裹,这其实就是 history 模式的路由,哈西模式的路由是 HashRouter ,另外你需要引入 Link ,这其实就是 a 标签。 react 中的路由入口是 Routes ,里面去写单个的路由,单个路由需要写 pathelement

这是用 a 标签去跳转页面,还有个方法是用 button 来跳转页面

Button

vue 中想要在组件中跳路由需要引入 useRouter,拿 routerpush 跳转

而 react 则是引入一个 hooksuseNavigate,调用这个 hooks 就可以得到一个跳转路由的方法

5 分钟掌握 react 中的 router_二级_02

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

const Home = () => {
    const navigate = useNavigate()
    return (
        <div>
            this is home
            <button onClick={() => navigate('/about')}>跳去关于页面</button>
        </div>
    )   
}

const About = () => <div>this is about</div>

const App = () => {
    return (
        <div className='app'>
            <BrowserRouter>
                <Link to='/'>首页 | </Link>
                <Link to='about'>关于</Link>

                <Routes>
                    <Route path='/' element={<Home />}></Route>
                    <Route path='/about' element={<About />}></Route>
                </Routes>
            </BrowserRouter>
        </div>
    );
};

export default App;

当然,history 可以有回退的功能,就是可以缓存历史访问的页面,你想要关掉这个功能,只需要给 navigate 加入第二个参数: replace: true

<button onClick={() => navigate('/about' , { replace: true })}>跳去关于页面</button>

这样,你就无法回退了

5 分钟掌握 react 中的 router_二级_03

你会发现 react 中需要引入的东西还是蛮多的,这里也总结下

BrowserRouter,HashRouter

history 模式和 hash 模式

Link

to 属性用于跳到指定的路径

Routes

路由的入口,类似 vuerouter-view

Route

单个路由匹配,path 用于匹配路径,element 用于匹配组件

useNavigate

const navigate = useNavigate()

路由传参

之前讲 vue 的路由传参有四种方法,这里 react 有两种方式进行传参

方法一:Search传参

这种方式就是原生 js 写法,直接 拼接 url 后面传递

其他页面想要拿到这个参数需要引入一个 hooksuseSearchParams ,这个方法的实例是一个数组,数组中用 get 拿到参数

import React from 'react';
import { BrowserRouter, Link, Routes, Route, useNavigate, useSearchParams } from 'react-router-dom'

const Home = () => {
    const navigate = useNavigate()
    return (
        <div>
            this is home
            <button onClick={() => navigate('/about?id=123' , { replace: true })}>跳去关于页面</button>
        </div>
    )   
}

const About = () => {
    let [ params ] = useSearchParams()
    console.log(params.get('id'));
    return (
        <div>this is about</div>
    )
}

const App = () => {
    return (
        <div className='app'>
            <BrowserRouter>
                <Link to='/'>首页 | </Link>
                <Link to='about'>关于</Link>

                <Routes>
                    <Route path='/' element={<Home />}></Route>
                    <Route path='/about' element={<About />}></Route>
                </Routes>
            </BrowserRouter>
        </div>
    );
};

export default App;

你若用 Link 这样跳转页面,useSearchParams 是拿不到参数的,这种方法只能用 navigate

方法二:Params传参

这种方法你就可以传参不用 ,直接用 / 拼接即可,为了防止这个参数也是个路径,你需要在接收方引入一个 hooksuseParams,并且传参时需要在 Routes 中的路径中指明 path 有参数,并且用:写上参数名

import React from 'react';
import { BrowserRouter, Link, Routes, Route, useNavigate, useSearchParams, useParams } from 'react-router-dom'

const Home = () => {
    const navigate = useNavigate()
    return (
        <div>
            this is home
            <button onClick={() => navigate('/about/123' , { replace: true })}>跳去关于页面</button>
        </div>
    )   
}

const About = () => {
    let params = useParams()
    console.log(params.id);
    return (
        <div>this is about</div>
    )
}

const App = () => {
    return (
        <div className='app'>
            <BrowserRouter>
                <Link to='/'>首页 | </Link>
                <Link to='about'>关于</Link>

                <Routes>
                    <Route path='/' element={<Home />}></Route>
                    <Route path='/about/:id' element={<About />}></Route>
                </Routes>
            </BrowserRouter>
        </div>
    );
};

export default App;

其实还有个 state 传参,不过现在最新的react版本已经不支持了

总结

  1. navigate('/about?id=123') 用 useSearchParams() 接受参数
  2. navigate('/about/123') 用 useParams() 接受参数

二级路由

下面实现一个二级页面的效果,一个布局栏页面中又有一个文章页面和一个发布页面

5 分钟掌握 react 中的 router_Layout_04

App.jsx

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

import Home from './views/Home';
import Layout from './views/Layout';
import Article from './views/layout-views/Article'
import Publish from './views/layout-views/Publish'

const App2 = () => {
    return (
        <div>
            <BrowserRouter>
                <Routes>
                    <Route path='/' element={<Home />}></Route>

                    {/* 二级路由 */}
                    <Route path='/layout' element={<Layout />}>
                        <Route path='article' element={<Article/>}></Route>
                        <Route path='publish' element={<Publish/>}></Route>
                    </Route>
                </Routes>
            </BrowserRouter>
        </div>
    );
};

export default App2;

Layout.jsx

import React from 'react';

import { Link, Outlet } from 'react-router-dom'

const Layout = () => {
    return (
        <div>
            <header style={{height: '80px', backgroundColor: '#eee'}}>header</header>
            <section style={{display: 'flex'}}>
                <aside style={{width: '200px', height: 'calc(100vh - 80px)', backgroundColor: 'yellow'}}>
                    <ul>
                        <li><Link to={'/layout/article'}>文章</Link></li>
                        <li><Link to={'/layout/publish'}>发布</Link></li>
                    </ul>
                </aside>
                <section>
                    <Outlet />
                </section>
            </section>
        </div>
    );
};

export default Layout;

这里的写法和 vue 有异曲同工之妙,二级路由无需打斜杠 / ,同样的在 layout 中再写一个 Route

二级路由需要引入一个入口 OutletRoute 中的页面才会在这里面展示

当然,我们也可以来到 layout 默认展示一个二级页面,实现方法有两种,这里以默认展示 article 页面为例

实现方法一:直接将 articlepath 去掉,换成 index

{/* 二级路由 */}
<Route path='/layout' element={<Layout />}>
    <Route index element={<Article/>}></Route>
    <Route path='publish' element={<Publish/>}></Route>
</Route>

这样做,article 的路径就是 layout 的路径

实现方法二: Navigate

{/* 二级路由 */}
<Route path='/layout' element={<Layout />}>
    <Route path='' element={<Navigate to='/layout/article'/>}></Route>
    <Route path='article' element={<Article/>}></Route>
    <Route path='publish' element={<Publish/>}></Route>
</Route>

写法上就是再写一个Route,用作重定向

最后

对比 vue,react 的路由写法还是比较复杂一点, react 中引入的东西还是比较多的,vue 无论一级二级路由都是一个写法,react 的写法是一级路由入口直接 BrowserRouter,而二级路由则需要写一个Outlet 才能展示。