# React Router(V5) > 将url地址和组件进行映射 [React Router: Declarative Routing for React.js](https://v5.reactrouter.com/web/guides/quick-start) #### 安装 ```bash # 安装v5 pnpm add react-router-dom@5 ``` ## helloRouter ```jsx /** * react router 使用步骤 * 1. 安装react-router-dom包 * 2. 在main.js 中引入BrowserRouter组件 * 3. 将BrowserRouter设置为根组件 */ ``` ```jsx // @/main.jsx import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import {BrowserRouter as Router} from "react-router-dom"; ReactDOM.createRoot(document.getElementById('root')).render( ) ``` ```jsx /** * 1. 引入Route组件 * 2. 设置 path 和 component属性, 访问对应路径,就会挂载对应组件 * 注意: 默认情况下Route并不是严格匹配 * 举例: 访问'/about',除了About组件,还会挂载Home组件 * 访问'/about/123',会挂载Home和About组件 * 所以要设置exact, 严格匹配 */ ``` ```jsx // @/App.jsx import { Route } from 'react-router-dom/cjs/react-router-dom.min' import Home from './components/Home' import About from './components/About' const App = ()=>{ return (
) } export default App ``` ## 路由跳转 Link / NavLink > 使用react router时, 不能使用a标签超链接切换路径, 因为会重新加载页面, 向服务器重新发请求 > >使用 Link组件或者NavLink组件 ```jsx //@/components/Menu.jsx import { Link } from 'react-router-dom' const Menu = () => { return ( ) } export default Menu ``` ```jsx /** * NavLink和Link类似,但可以指定激活路径的链接样式 * 同样需要设置严格模式 exact * activeClassName 为激活的链接添加类名 * activeStyle 为激活的标签添加样式 */ ``` ```jsx //@/components/Menu.jsx import { NavLink } from 'react-router-dom' import classes from './Menu.module.css' const Menu = () => { return ( ) } export default Menu ``` ```css /* @/src/components/Menu.module.css */ a:link, a:visited { color: black; text-decoration:none; } a:hover { color: skyblue; } a.active { color:green; } ``` ## 两种路由模式 BrowserRouter HashRouter ```jsx /** * 1. 地址栏: hash多了个#号, http://127.0.0.1:5173/#/ http://127.0.0.1:5173/#/about * 2. 开发过程: 没有区别 * 3. 部署过程: * BrowserRouter是直接通过url地址进行跳转 * 直接通过链接进行跳转,没有经过服务器,没有问题 * 直接在地址栏输入或者刷新,会向服务器发送请求,404 * 解决方案: 1. 换成HashRouter 2.需要修改服务器,将所有请求都转发到index.html * HashRouter是url中的hash来对地址进行匹配, 服务器不会判断hash */ ``` ```conf # 修改nginx配置 server { location / { root html; #index index.html; try_files $url /index.html; } } ``` ## 路由传参 ### component挂载组件 ```js /** * component直接传组件的类,会自动创建组件并传递参数 * match: 匹配的信息 * isExact 检查路径是否完全匹配 * params 请求的参数 * location: 地址信息 * pathname 当前路径 * search 搜索参数 * history: 历史记录的信息, 主要用来控制页面的跳转 * goForward() 前进 * goBack() 后退 * go(n) 参数为数字 * push() 跳转,有历史记录, 需要一个location作为参数 * replace() 替换,没有历史记录 */ ``` ```jsx //@/components/Student.jsx const Student = (props)=>{ console.log(props) const clickHandler = ()=>{ props.history.push({ pathname:'/student/2', state: { // 在props.location.state可以找到 name: 'test' } }) } const clickHandler2 = ()=>{ props.history.replace({ pathname:'/student/3' }) } return (

{JSON.stringify(props.match.params)}

{JSON.stringify(props.location.state)}


) } export default Student ``` ```jsx // src/App.jsx import { Route } from 'react-router-dom/cjs/react-router-dom.min' import Home from './components/Home' import About from './components/About' import Menu from './components/Menu' import Student from './components/Student' const App = ()=>{ return (

) } export default App ``` ```jsx // src/components/Menu.jsx import { NavLink } from 'react-router-dom' import classes from './Menu.module.css' const Menu = () => { return ( ) } export default Menu ``` ### render挂载组件 ```js // 这样挂载组件有缺点, 传入的是类,没办法自定义属性或者传递参数 // 解决方法 用render或者children ``` ```js { console.log(routerProps) return }}/> ``` ### children挂载组件 ```js // src/App.jsx } /> // 或者 ``` ```jsx // src/components/Student.jsx import { useHistory, useRouteMatch,useLocation,useParams } from 'react-router-dom' const Student = ()=>{ /** * 用钩子函数获取路由 */ const match = useRouteMatch() const location = useLocation() const history = useHistory() const params = useParams() const clickHandler = ()=>{ history.push({ pathname:'/student/2', state: { // 在props.location.state可以找到 name: 'test' } }) } const clickHandler2 = ()=>{ history.replace({ pathname:'/student/3' }) } return (

{JSON.stringify(params)}

{JSON.stringify(location.state)}


) } export default Student ``` ## 路由嵌套 > 访问/about显示About组件, 访问/about/hello, 既显示About组件, 也显示hello组件 ```jsx // src/App.jsx // ... // exact 去掉 //... ``` 或者在``组件中添加 ```jsx // src/components/About.jsx // ... // exact 去掉 // ... ``` 为了避免要手动补全路径, 使用钩子获取当前组件path ```jsx // src/components/About.jsx import {useRouteMatch,Route} from 'react-router-dom' import Hello from './Hello' const About = () => { const {path} = useRouteMatch() return (

about页面

) } export default About ``` ## prompt提示组件 > 离开当前路由时提示 ```jsx import { useState } from 'react' import { Prompt } from 'react-router-dom' const Form = ()=>{ const [input, setInput] = useState('') const [showPrompt, setShowPrompt] = useState(false) const changeHandler = (e)=>{ const format = e.target.value.trim() setInput(format) setShowPrompt(!!format) } return (

表单

) } export default Form ``` ## Redirect重定向组件 ```js /** * Redirect 重定向组件 * to 跳转的url,可以是string,也可以是location * 默认是通过replace跳转 * 添加push属性,改为push跳转 */ ``` ```jsx {loggedIn ? : } ``` ```jsx ``` ## Switch组件 > 常用于权限判断路由权限 和`Redirect`一起用, `Redirect` 要添加from ```jsx import { Redirect, Route, Switch } from "react-router"; let routes = ( ); ```