2021.12.15 每天进步一点点: react-router-dom@6 学习笔记


react-router-dom

官方文档: https://reactrouter.com/docs/en/v6/api#routing

安装

安装当前最新版本:

yarn add react-router-dom

or:

安装指定版本:

yarn add react-router-dom@6


web相关API
  1. BrowserRouter
  2. HashRouter
  3. Link
  4. NavLink
  5. Navigate
  6. Outlet
  7. useOutletContext
  8. Router
  9. Routes & Route
  10. generatePath
  11. history
  12. useNavigate
  13. useParams
  14. useRoutes
    matchPath
    matchRoutes
    createRoutesFromChildren
    useResolvedPath
    useHref
    useLocation
    useNavigationType
    useLinkClickHandler
    resolvePath
    useSearchParams

简单介绍

react-router包含了绝大多数的路由方法。

react-router-dom包含了react-router和额外的方法。

react-router-dom = react-router+ <BrowserRouter> + <HashRouter> + <Link>

<xxxRouter>有很多种,在web浏览器中,我们选择<BrowserRouter><HashRouter>


批量解释
BrowserRouter(官方推荐)

BrowserRouter存储了地址栏信息和导航。

用法
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.render(
  <Router>
    {/* The rest of your app goes here */}
  </Router>,
  root
); 
HashRouter(官方不推荐使用)

当特定的URL因为某些原因不能或不应该发送到服务器时,使用HashRouter。

官方文档提示:我们强烈建议你不要使用HashRouter,除非你完全无法避免使用它

Link

对应生成一个<a href>标签。可以在任何地方使用

语法
import {Link} from 'react-router-dom'

<Link to='/url'>xxx</Link>

or:

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

<Link to='url'>xxx</Link>

假定当前地址栏完整路径是http://localhost:3000/demo

  1. 第一种带/的写法,

    点击会跳转到父路径/url

    即跳转到http://localhost:3000/url

  2. 第二种不带/的写法,

    点击会跳转到当前路径/url

    此时,/url 就是当前路径的子路径

    即跳转到http://localhost:3000/demo/url

NavLink

是一种特殊的Link,通常用作面包屑或tab栏导航,

NavLink会显示出当前哪个选项被点击或选择了。

NavLink有两个属性,即styleclassName,二选一

style代表行内样式,className代表外联样式。

用于显示被点击后的样式。

语法
import {NavLink} from 'react-router-dom'

<NavLink 
    to="tab1"
    style={({isActive}) => isActive ? activeStyle : undefined}>tab1</NavLink>
    

or:

import {NavLink} from 'react-router-dom'

<NavLink 
    to="tab1"
    className={({isActive}) => isActive ? activeClassName : undefined}>tab1</NavLink>
    
Navigate

替换导航。

Navigate会把当前地址栏的地址,替换成Navigate组件中to后面的新地址。

语法
import { Navigate } from 'react-router-dom';

<Navigate to='/url' />
demo
import React, {useState} from 'react';
import { Navigate } from 'react-router-dom';

function Demo4() {
    const [isClick, setClick] = useState(false);
    const handleClick = () => {
        setClick(true);
    }
    return (
        <div>
            <div>hello demo4 !</div>
            <div>
                <button onClick={handleClick}>click to /</button>
            </div>
            {isClick && (<Navigate to='/' />)}
        </div>
    )
}

export default Demo4;
Outlet

放在父组件里,用来告诉浏览器,在渲染的时候,

  1. 如果路由匹配到父路由,就渲染父组件

  2. 如果路由匹配到子路由,就渲染子路由

demo
// 父路由 /demo5
// 子路由1 /demo5/child1
// 子路由2 /demo5/child2

// /scr/index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { Child1, Child2, Demo5 } from './demo5';

function App() {
    return (
        <Routes>
            <Route path='/demo5' element={<Demo5 />}>
                <Route path='child1' element={<Child1 />} />
                <Route path='child2' element={<Child2 />} />
            </Route>
        </Routes>
    )
}

render(
    <Router>
        <App />
    </Router>,
    document.querySelector('#root')
);

// /src/demo5.js
import React from 'react';
import { Outlet } from 'react-router-dom';

// 子组件1
export function Child1() {
    return (
        <div>
            hello, child 1111 !
        </div>
    )
}

// 子组件2
export function Child2() {
    return (
        <div>
            hello, child 2222 !
        </div>
    )
}

// 父组件
export function Demo5() {
    return (
        <div>
            hello, demo 555 !
            {/*outlet组件写在父组件里*/}
            <Outlet />
        </div>
    )
}
useOutletContext()

把父组件的状态传给子组件使用。

Router

一般会用作BrowserRouterHashRouter引入时的缩写

然后在书写时,用Router替代BrowserRouter或HashRouter

demo
import {BrowserRouter as Router} from 'react-router-dom';

Routes & Route

两者都是基于当前路径去渲染react路由的一种基础方式。

Routes是用来包裹住Route的。就是之前版本的Switch

Route之间还可以做嵌套,形成父子路由。

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

<Routes>
    <Route path='/demo5' element={<Demo5 />}>
        <Route path='child1' element={<Child1 />} />
        <Route path='child2' element={<Child2 />} />
    </Route>
</Routes>
generatePath()

generatePath 衍生路径,也可以叫生成路径

它接收一个路径和一个参数值,然后生成一个新的路径

demo
import {generatePath} from 'react-router-dom';

console.log(generatePath("/users/:id", { id: 42 })); // "/users/42"

console.log(generatePath("/files/:type/*", {
  type: "img",
  "*": "cat.jpg"
})); // "/files/img/cat.jpg"
history

history库是react路由的唯一依赖,很多react路由中的方法都是直接取自于history库,

比如Location, To, Path, State等。

history库需要单独安装和学习。

useNavigate

react-router-dom@6取消了重定向方法

而useNavigate可以做重定向

语法:

import { useNavigate } from "react-router-dom";

function Demo() {
    let navigate = useNavigate();

    const handleClick = () => {
        navigate('/url', { replace: true });
    }
    return (
        <div>
            <button onClick={handleClick}>click to redirect</button>
        </div>
    )
}
useParams

用来在对应子路由中获取动态子路由的参数值

动态路由形式:

path=':userId'

demo
// /src/index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import Demo6 from './demo6';

render(
    <Router>
        <Demo6 />
    </Router>,
    document.querySelector('#root')
);

// /src/demo6.js
// 子路由对应的子组件是Child1
// useParams在Child1组件中使用
import React from 'react';
import { Routes, Route, useParams } from 'react-router-dom';

function Child1() {
    let { userId } = useParams();
    console.log(userId);
    return (
        <div>hello , child1 !</div>
    )
}

function Child2() {
    return (
        <div>
            hello, child 2222 !
        </div>
    )
}

function Demo6() {
    return (
        <Routes>
            <Route path="/demo6">
                <Route path=":userId" element={<Child1 />} />
                <Route path="me" element={<Child2 />} />
            </Route>
        </Routes>
    )
}

export default Demo6;

比如 路径为: http://localhost:3000/demo6/hello

userId就是’hello’

比如 路径为: http://localhost:3000/demo6/2333

userId就是’2333’

注意: 用useParams 时,没有使用Outlet,也成功匹配了子路由

useRoutes

路由的另一种写法

就是把嵌套形式的路由,改成函数形式的路由

具体用哪一种,看个人喜好了。

这里写的demo中有点问题,

就是输入子路由之后,并没有渲染子组件。

目前还没有找到合适的方法去解决, 如果有知道的,欢迎评论讨论。

demo
// index.js
import React from 'react';
import { render } from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import Demo7 from './demo7';

render(
    <Router>
        <Demo7 />
    </Router>,
    document.querySelector('#root')
);

// demo7.js
import React from 'react';
import { useRoutes } from 'react-router-dom';

function R() {
    return (
        <div>R </div>
    )
}

function R1() {
    return (
        <div>R1 </div>
    )
}

function R2() {
    return (
        <div>R2 </div>
    )
}

function C1() {
    return (
        <div>这里是C1 </div>
    )
}

function C2() {
    return (
        <div>这里是C2 </div>
    )
}

function Demo7() {
    let element = useRoutes([
        {path: '/', element: <R />},
        {
            path: 'r1',
            element: <R1 />,
            children: [
                {
                    path: 'c1',
                    element: <C1 />
                },
                {
                    path: 'c2',
                    element: <C2 />
                },
            ]
        },
        { path: 'r2', element: <R2 /> },
    ])

    return element;
}

export default Demo7;

另附:

  • 获取三种路由传参:
https://blog.csdn.net/yusirxiaer/article/details/122442993
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值