react router 可以将url地址和组件进行映射
当用户访问某个地址时,与其对应的组件会自动的挂载
react router 使用步骤
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(
);
将路由和组件进行映射
使用Route来映射地址和组件
属性:
当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 (App组件Home}/>About}/> );
}export default App;
在使用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 (- {/*主页*/}
{textDecoration:"underline"}}to="/">主页 - {/*关于*/}
{textDecoration:"underline"}}to="/about">关于
);
};export default Menu;
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构建的组件,它会自动创建组件并且会自动传递参数
match – 匹配的信息
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 (Home}/>About}/>{/*/student/:id 会匹配到 /student/xxx*/}Student}/> );
}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 ({stu.id} --- {stu.name});
};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 (关于我们,其实是师徒4人
- 孙悟空
- 猪八戒
- 沙和尚
- 唐僧
);
};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 (Home}/>About}/>(routePros)=>{return ...routePros}/>}}/> );
}export default App;
children 也可以用来指定被挂载的组件
用法有两种:
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 (Home}/>About}/>{/* }/>*/}{/* }/>*/} */} {/**/}{/* {routeProps => }*/}{/* */} );
}export default App;
除了可以通过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 ({stu.id} --- {stu.name});
};export default Student;
使用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 (关于我们,其实是师徒4人
- 孙悟空
- 猪八戒
- 沙和尚
- 唐僧
`${path}/hello`}> );
};export default About;
可以将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 (Home}/>路径错误 );
}export default App;
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 (isPrompt}message={"将要离开页面!确认吗?"}/>表单
e => setIsPrompt(e.target.value.trim().length !== 0)}/> );
};export default MyForm;
prompt组件的message属性,同时还可以传入一个方法来接收要传入的文字, 但是要注意的是, 使用三元运算符操作, 可以向其中直接传入文字, 但是如果使用if else来做判断,那么将无法直接向其中传入文字
() => {this.state.isOpen? false: "您确定要离开该页面吗?"
}}/>
if else判断无法向组价中直接传入文字内容, 但是幸好, message能够接收一个方法, 而这个方法, 最终只需要返回一个true或者false就可以, 不管中间你写什么样的代码都无所谓
(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 用于跳转页面
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 (Home}/>"/login"}> {isLogin ? :"/login"}/>} {/* */}路径错误 );
}export default App;
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 (App
}> }> }/> );
};
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 ({stu.id} --- {stu.name}
);
};export default Student;
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 (App
}> }> }> }> );
};export default App;
About.js
import React from 'react';
import {Outlet} from "react-router-dom";const About = () => {return ( );
};export default About;
Navigate 组件用来跳转到指定的位置
默认使用push跳转
About.js
import React from 'react';
import {Outlet, Navigate} from "react-router-dom";const About = () => {return ( );
};export default About;
import React from 'react';
import {Link, NavLink} from "react-router-dom";const Menu = () => {return (- 主页
- 关于
({isActive})=>{return isActive?{backgroundColor:"yellow"}:null}}to="/student/2">学生
);
};export default Menu;
下一篇:javaScript型参与实参