react-router v5+v6(基础使用)

react-router

react-router-v5

react router 可以将url地址和组件进行映射
当用户访问某个地址时,与其对应的组件会自动的挂载

react router 使用步骤

  1. 引入react-router-dom包
  2. 在index.js中引入BrowserRouter组件
  3. 将BrowserRouter设置为根组件

index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter as Router} from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <Router>
        <App />
    </Router>
);

将路由和组件进行映射
使用Route来映射地址和组件
属性:

  • path 映射的url地址
  • component 要挂载的组件
  • exact 路径是否完整匹配,默认值false

当Route的路径被访问,其对应组件就会自动挂载
注意 默认情况下Route并不是严格匹配
只要url地址的头部和path一致,组件就会挂载,不会检查子路径
App.js

import {Route} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";

function App() {
  return (
    <div className="App">
      App组件
        <Route exact path="/" component={Home}/>
        <Route exact path="/about" component={About}/>
    </div>
  );
}

export default App;

NavLink

在使用react router时,一定不要使用a标签来创建超链接
因为a标签创建的超链接,会自动向服务器发送请求重新加载页面
而我们不希望这种情况发生

可以使用Link组件来创建超链接
NavLink和Link作用相似,只是可以指定链接激活后的样式

Menu.js

import React from 'react';
import {Link, NavLink} from "react-router-dom";
import classes from "./Menu.module.css";

const Menu = () => {
    return (
        <div>
            <ul>
                <li>
                    {/*<Link to="/">主页</Link>*/}
                    <NavLink
                        exact
                        // activeClassName={classes.active}
                        activeStyle={{textDecoration:"underline"}}
                        to="/">主页</NavLink>
                </li>
                <li>
                    {/*<Link to="/about">关于</Link>*/}
                    <NavLink
                        exact
                        // activeClassName={classes.active}
                        activeStyle={{textDecoration:"underline"}}
                        to="/about">关于</NavLink>
                </li>
            </ul>
        </div>
    );
};

export default Menu;

HashRouter与BrowserRouter

HashRouter 会通过url地址中的hash值来对地址进行匹配
BrowserRouter 直接通过url地址进行组件的跳转
使用过程中和普通的url地址没有区别

react router 可以将url地址和组件进行映射
当用户访问某个地址时,与其对应的组件会自动的挂载
当我们通过点击Link构建的链接进行跳转时,跳转并没有经过服务器,所以没有问题
但是当我们刷新页面,或通过普通链接进行跳转时,会向服务器发送请加载数据
这时的请求并没有经过react router 所以会返回404

解决方案:
1.使用HashRouter,服务器不会去判断hash值,所以使用HashRouter后请求将会由React Router处理
2.修改服务器的配置,将所有请求都转发到index.html

组件component

component用来指定路由匹配后被挂载的组件
component需要直接传递组件的类
通过component构建的组件,它会自动创建组件并且会自动传递参数
match – 匹配的信息

  • isExact 检查路径是否完全匹配
  • params 请求的参数
    location – 地址信息
    history – 控制页面的跳转
  • push() 跳转页面
  • replace() 替换页面
import {Route} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Menu from "./components/Menu";
import Student from "./components/Student";

function App() {
    return (
        <div className="App">
            <Menu/>
            <Route exact path="/" component={Home}/>
            <Route path="/about" component={About}/>
            {/*
                /student/:id 会匹配到 /student/xxx
            */}
            <Route path="/student/:id" component={Student}/>
        </div>

    );
}

export default App;

student.js

import React from 'react';

const STU_DATA = [
    {
        id:1,
        name:'孙悟空'
    },
    {
        id:2,
        name:'猪八戒'
    },
    {
        id:3,
        name:'沙和尚'
    },
    {
        id:4,
        name:'唐僧'
    },
];

const Student = (props) => {

    console.log(props);
    const stu = STU_DATA.find(item => item.id === +props.match.params.id);

    return (
        <div>
            {stu.id} --- {stu.name}
        </div>
    );
};

export default Student;

About.js

import React from 'react';

const About = (props) => {
    // console.log(props);
    const clickHandler = ()=>{
        // push()需要一个location作为参数
        // props.history.push({
        //     pathname:'/student/2'
        // });

        props.history.replace({
            pathname:'/student/2',
            state:{name:'哈哈'}
        });
    };
    return (
        <div>
            <button onClick={clickHandler}>点我一下</button>
            <h2>关于我们,其实是师徒4</h2>
            <ul>
                <li>孙悟空</li>
                <li>猪八戒</li>
                <li>沙和尚</li>
                <li>唐僧</li>
            </ul>
        </div>
    );
};

export default About;

render也可以用来指定要挂载的组件
render需要一个回调函数作为参数,回调函数的返回值会最终被挂载
render不会自动传递三个属性

import {Route} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Menu from "./components/Menu";
import Student from "./components/Student";

function App() {
    return (
        <div className="App">
            <Menu/>
            <Route exact path="/" component={Home}/>
            <Route path="/about" component={About}/>
            <Route path="/student/:id" render={(routePros)=>{
               return <Student {...routePros}/>
            }}/> 
        </div>

    );
}

export default App;

children 也可以用来指定被挂载的组件
用法有两种:

  1. 和render类似,传递回调函数
    当children设置一个回调函数时,该组件无论路径是否匹配都会挂载
  2. 可以传递组件
import {Route} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Menu from "./components/Menu";
import Student from "./components/Student";

function App() {
    return (
        <div className="App">
            <Menu/>
            <Route exact path="/" component={Home}/>
            <Route path="/about" component={About}/>
            {/*<Route path="/student/:id" children={(routeProps)=> <Student {...routeProps}/>}/>*/}
            {/*<Route path="/student/:id" children={<Student/>}/>*/}
            <Route path="/student/:id">
                <Student/>*/}
            </Route>

            {/*<Route path="/student/:id">*/}
            {/*    {routeProps => <Student {...routeProps}/>}*/}
            {/*</Route>*/}
        </div>

    );
}

export default App;

useRouteMatch() useLocation() useParams()

除了可以通过props获取三个对象外,也可以通过这三个钩子函数来获取

Studet.js

import React from 'react';
import {useHistory, useLocation, useParams, useRouteMatch} from "react-router-dom";

const STU_DATA = [
    {
        id:1,
        name:'孙悟空'
    },
    {
        id:2,
        name:'猪八戒'
    },
    {
        id:3,
        name:'沙和尚'
    },
    {
        id:4,
        name:'唐僧'
    },
];

const Student = (props) => {

    // console.log(props);
    // const stu = STU_DATA.find(item => item.id === +props.match.params.id);
    const match = useRouteMatch();
    const location = useLocation();
    const history = useHistory();
    const {id} = useParams();

    // const stu = STU_DATA.find(item => item.id === 1);
    const stu = STU_DATA.find(item => item.id === +id);


    return (
        <div>
            {stu.id} --- {stu.name}
        </div>
    );
};

export default Student;

路由嵌套 useRouteMatch()

使用useRouteMatch钩子,可以获取到当前页面路径

About.js

import React from 'react';
import Hello from "./Hello";
import {Route, useRouteMatch} from "react-router-dom";

const About = (props) => {

    const {path} = useRouteMatch();
    const clickHandler = ()=>{


    };
    return (
        <div>
            <button onClick={clickHandler}>点我一下</button>
            <h2>关于我们,其实是师徒4</h2>
            <ul>
                <li>孙悟空</li>
                <li>猪八戒</li>
                <li>沙和尚</li>
                <li>唐僧</li>
            </ul>

            <Route path={`${path}/hello`}>
                <Hello/>
            </Route>
        </div>
    );
};

export default About;

Switch组件 (已弃用)

可以将Route统一放到一个Switch中,
一个Switch中只会有一个路由显示

import {Route, Switch} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Menu from "./components/Menu";

function App() {
    return (
        <div className="App">
            <Menu/>
            <Switch>
                <Route exact path="/" component={Home}/>
                <Route path="/about">
                    <About/>
                </Route>
                <Route path="*">
                    <div>路径错误</div>
                </Route>
            </Switch>
        </div>

    );
}

export default App;

Prompt

Prompt组件作用是,在用户准备离开该页面时, 弹出提示, 返回true或者false, 如果为true, 则离开页面, 如果为false, 则停留在该页面,
prompt组件里有一个message属性,该属性就是在用户离开页面时, 所提示的文字内容
prompt组件中还有一个when属性, 就是渲染该组件的条件, 应该传入一个布尔值,值为true时,则渲染该组件

import React, {useState} from 'react';
import {Prompt} from "react-router-dom";

const MyForm = () => {

    const [isPrompt, setIsPrompt] = useState(false);

    return (
        <div>
            <Prompt
                when={isPrompt}
                message={"将要离开页面!确认吗?"}/>
            <h2>表单</h2>
            <input
                type="text"
                onChange={e => setIsPrompt(e.target.value.trim().length !== 0)}
            />
        </div>
    );
};

export default MyForm;

prompt组件的message属性,同时还可以传入一个方法来接收要传入的文字, 但是要注意的是, 使用三元运算符操作, 可以向其中直接传入文字, 但是如果使用if else来做判断,那么将无法直接向其中传入文字

<Prompt
   message = {() => {
   this.state.isOpen? false: "您确定要离开该页面吗?"
}}
  />

if else判断无法向组价中直接传入文字内容, 但是幸好, message能够接收一个方法, 而这个方法, 最终只需要返回一个true或者false就可以, 不管中间你写什么样的代码都无所谓

<Prompt
   message = {(location)=>{
     if(!isPrompt) {
       let leave = window.confirm("您确定要离开该页面吗?")          
       if(!leave) {
         return false
       }          
     }else {
       setIsPrompt(false)
     return false
     }
   }}
  />

【总结】:Prompt 有两个属性:message-当用户离开页面时给出的提示信息,when-是否渲染,设置为 true 时,离开页面时总会渲染,设置为 false 时,离开页面时不会渲染。我们就可以利用when设置渲染的时机,当用户对页面内容进行编辑,且未保存时离开,设置when=true,其他情况设置when=false。

Redirect

Redirect 用于跳转页面

import {Redirect, Route, Switch} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Menu from "./components/Menu";
import Student from "./components/Student";
import Hello from "./components/Hello";
import MyForm from "./components/MyForm";
import {useState} from "react";
import Login from "./components/Login";

function App() {
    const [isLogin, setIsLogin] = useState(false);

    return (
        <div className="App">
            <Menu/>
            <Switch>
                <Route exact path="/" component={Home}/>
                <Route path="/about">
                    <About/>
                </Route>
                <Route path={"/login"}>
                    <Login/>
                </Route>


                <Route path="/form">
                    {
                        isLogin ? <MyForm/>:
                            <Redirect to={"/login"}/>
                    }
                </Route>

                {/*<Redirect from={"/abc"} to={"/form"}/>*/}

                <Route path="*">
                    <div>路径错误</div>
                </Route>
            </Switch>
        </div>

    );
}

export default App;

react-router-v6

Routes v6 中新增加的组件
作用和Switch类似,都是用于Route的容器
Routes中Route只有一个会被匹配
v6中,Route的component render children都变了
需要通过element来指定要挂载的组件
App.js

import React from 'react';
import {Route, Routes} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Menu from "./components/Menu";
import Student from "./components/Student";

const App = () => {
    return (
        <div>
            <h1>App</h1>
            <Menu/>
            <Routes>
                <Route path="/" element={<Home/>}></Route>
                <Route path="about" element={<About/>}></Route>
                <Route path="student/:id" element={<Student/>}/>
            </Routes>

        </div>
    );
};

参数和钩子

useParams()来获取参数
useLocation()获取当前的地址信息
useMatch()用来检查当前url是否匹配某个路由
useNavigate()获取一个用于条件页面的函数

import React from 'react';
import {useLocation, useParams, useMatch, useNavigate} from "react-router-dom";

const STU_DATA = [
    {
        id:1,
        name:'刘备'
    },
    {
        id:2,
        name:'关羽'
    },
    {
        id:3,
        name:'沙和尚'
    },
    {
        id:4,
        name:'唐僧'
    },
];

const Student = () => {
    // 可以使用useParams()来获取参数
    const {id} = useParams();

    const location = useLocation();// 获取当前的地址信息

    // 如果路径匹配,则返回一个对象,不匹配则返回null
    //const match = useMatch("/student/:id");// 用来检查当前url是否匹配某个路由

    // useNavigate获取一个用于条件页面的函数
    const nav = useNavigate();


    const stu = STU_DATA.find(item => item.id === +id);

    const clickHandler = () =>{
        // nav('/about'); // 使用push,会产生历史记录
        nav('/about', {replace: true}); // 使用replace 不会产生新的记录
    };

    return (
        <div>
            <button onClick={clickHandler}>点我一下</button>
            <h2>{stu.id} --- {stu.name}</h2>
        </div>
    );
};

export default Student;

嵌套路由和Outlet

Outlet 用来表示嵌套路由中的组件
当嵌套路由中的路径匹配成功了,Outlet则表示嵌套路由中的组件
当嵌套路由中的路径没有匹配成功,Outlet就什么都不是
App.js

import React from 'react';
import {Route, Routes} from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";
import Student from "./components/Student";
import Hello from "./components/Hello";
import Abc from "./components/Abc";

const App = () => {
    return (
        <div>
            <h1>App</h1>
            <Routes>
                <Route path="/" element={<Home/>}></Route>
                <Route path="about" element={<About/>}>
                    <Route path="hello" element={<Hello/>}></Route>
                    <Route path="abc" element={<Abc/>}></Route>
                </Route>
            </Routes>
        </div>
    );
};

export default App;

About.js

import React from 'react';
import {Outlet} from "react-router-dom";

const About = () => {
    return (
        <div>
            <Outlet/>
        </div>
    );
};

export default About;

Navigate组件

Navigate 组件用来跳转到指定的位置
默认使用push跳转

About.js

import React from 'react';
import {Outlet, Navigate} from "react-router-dom";

const About = () => {
    return (
        <div>
            <Navigate to="/student/1" replace/>
            <Outlet/>
        </div>
    );
};

export default About;

NavLink

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

const Menu = () => {

    return (
        <div>
          <ul>
              <li>
                  <Link to="/">主页</Link>
              </li>
              <li>
                  <Link to="/about">关于</Link>
              </li>
              <li>
                  <NavLink
                      style={
                          ({isActive})=>{
                              return isActive?
                                  {backgroundColor:"yellow"}:
                                  null
                          }
                      }
                      to="/student/2">学生</NavLink>
              </li>
          </ul>
        </div>
    );
};

export default Menu;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_聪明勇敢有力气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值