v4/v5用法和基本理念一致,v2,v3差异较大
v4和v4之前的版本比较:
- v4:文档版本,属于动态路由
react-route被拆分成多个包发布,可以按需引用:- react-router: 路由基础库
- react-router-dom:适用于浏览环境的再次封装
- react-router-native:适用于react-native环境的再次封装
- react-router-config:静态路由配置助手
- 引入方式:
import React from 'react-router/Router'
- v5:进行一些新特性的添加和改进,完全兼容v4
- 引入方式:
import {React, Switch} from 'react-router' - 支持数组匹配:
<Route path={["user/:id",info/>:id]} compnent={User}
- 引入方式:
原理:检测浏览器url变化,截获url地址,然后进行url路由匹配
方式:
1.hash:锚点的方式,可以通过hashchange事件监听锚点的变化:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="btn">点击</button>
<script>
const btnDom = document.getElementById('btn')
btnDom.addEventListener('click', ()=>{
location.href = '#' +Math.floor((Math.random()*10))
})
window.addEventListener('hashchange', e=>{
const {oldURL,newURL} = e;
console.log('老url',oldURL)
console.log('新url',newURL)
console.log('hash值',location.hash)
})
</script>
</body>
</html>2.html5:history模式(页面刷新的时候,浏览器会向服务器发请求,需要服务器支持)
分类:
- BrowserRouter对应History模式
- HashRouter对应Hash模式
每个Router都会创建一个history对象,用来保持当前位置的追踪
import './App.css';
import {Home} from './components/Home'
import {About} from './components/About'
import {BrowserRouter, Route, Link, HashRouter} from 'react-router-dom'
function App() {
return (
<div className="App">
<BrowserRouter>
{/*匹配的路由不带#:http://localhost:3000/home}*/}
<Route path="/home" component={Home} />
</BrowserRouter>
<HashRouter>
{/*匹配的路由带#:http://localhost:3000/#/about}*/}
<Route path="/about" component={About} />
</HashRouter>
</div>
);
}
export default App;- 一个具有渲染方法的普通react组件,路由匹配成功渲染该组件
- 常用属性
- path: 路由匹配规则,可以省略,字符串类型
- exact: 设置为true表示路径严格匹配
- component:要渲染的组件
- render:函数形式,进行一些逻辑操作,可以替代component,path匹配的时候才执行
- children:函数形式,进行一些逻辑操作,可以替代component,任何时候都会执行
- 优先级:children > component > render
<BrowserRouter>
{/*匹配的路由不带#:http://localhost:3000/home}*/}
<Route path="/home" component={Home} />
{/*如果没有path,无论什么路径都会匹配到*/}
{/*<Route component={Info}/>*/}
{/*严格匹配根路径*/}
<Route path="/" exact={true} component={Info} />
{/*路径匹配时才渲染*/}
<Route path="/render" render={() => <h1>我是render渲染的</h1>} />
{/*路径不匹配也会渲染*/}
<Route
path="/children"
children={({match}) => {
console.log(match) //路径匹配到会打印出match对象,匹配不到会是null
return <h1>我是children渲染的</h1>;
}}
/>
</BrowserRouter>- 最多只能匹配一个组件
- 可以将Route组件分组
- 可以实现404页面渲染
<BrowserRouter>
<Switch>
{/*http://localhost:3000/home 只显示Info组件,即如果第一个组件匹配到了,不会匹配后面的组件*/}
<Route path="/" component={Info} />
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
{/*匹配不到时匹配NotFound组件,提升用户的体验*/}
<Route component={NotFound} />
</Switch>
</BrowserRouter>声明式的可访问导航
Link常用属性:
- to:字符串或对象类型,对象类型时包含pathname,search,state属性
- replace:为true表示替换当前的历史记录
<BrowserRouter>
<div>
{/*Link组件一定要在BrowserRouter中,点击链接切换,实现局部刷新*/}
<Link to="/home" replace>跳转home</Link>
{/*to属性可以是对象,search表示带的参数*/}
<Link to={{ pathname: "/about", search: "?name=abc" }}>跳转about</Link>
</div>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
</BrowserRouter>NavLink:特殊版的Link,当匹配的时候可以用activeStyle添加样式
<BrowserRouter>
<div>
{/*匹配时会应用activeStyle*/}
<NavLink to="/home" activeStyle={{ color: "red" }}>
跳转home
</NavLink>
<Link to={{ pathname: "/about", search: "?name=abc" }}>
跳转about
</Link>
</div>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
</BrowserRouter>- 重定向组件
- 属性:
- to: 必须属性
- push: 为true时,把当前地址推入history中,通过history.push实现
- from: 将要进入的url
- exact:严格模式匹配
<BrowserRouter>
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
{/*模拟登录就跳到Info组件,没有登录就跳到Home组件*/}
<Route path="/info" render={()=>{
return isLoginIn ? <Info/> : <Redirect to="/home"/>
}} />
</BrowserRouter>实现编程式导航
修改Home组件,点击按钮可以跳到About组件:
import React from "react";
export function Home(props) {
function handleClick() {
props.history.push("/about"); //只有通过路由跳转的props才有history属性
}
return (
<div>
<h1>我是Home组件</h1>
<button onClick={handleClick}>跳转到about</button>
</div>
);
}包裹没有经过路由匹配的页面,从props中获取history对象
路由规则不是预先确定的,是在渲染过程中确定的
<BrowserRouter>
<Route path="/home" component={Home} />
<Route path="/about/:id" component={About} />
</BrowserRouter>当输入url为http://localhost:3000/about/1时,在About组件中通过match对象可以拿到id:
import React from 'react'
export function About(props){
console.log(props.match.params.id) //拿到路由中的id:1
return <div>
<h1>我是About组件</h1>
</div>
}二级路由,如在Home组件中再进行路由的配置:
import React from "react";
import { Route, Link } from "react-router-dom";
import { About } from "./About";
import { Info } from "./Info";
export function Home(props) {
return (
<div>
<h1>我是Home组件</h1>
<div>
<Link to={`${props.match.path}/one`}>二级路由一</Link>
<Link to="/home/two">二级路由二</Link>
</div>
<Route path={`${props.match.path}/one`} component={About} />
<Route path="/home/two" component={Info} />
</div>
);
}📚 本项目源码
