安装依赖:npm i -S react-router-dom
使用时,路由器 Router
就是 React
的一个组件。
Router
组件本身只是一个容器,真正的路由要通过 Route
组件定义。
Route组件的path
属性用来指定路由的匹配规则。
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route} from 'react-router-dom';
const Home = () => (<div>首页</div>)
const About = () => (<div>关于我们</div>)
const App = () => (
<Router>
<div>
<Route path={
"/main"} component={
Home} />
<Route path={
"/about"} component={
About} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
如果不写,那么不管路径是否匹配,总是会加载所有组件。
<Router>
<div>
<Route component={
Home} />
<Route component={
About} />
</div>
</Router>
HashHistory
,路由将通过URL的hash部分(#
)切换,URL的形式类似http://localhost:3000/#/
import React from 'react';
import ReactDOM from 'react-dom';
import {
HashRouter as Router, Route} from 'react-router-dom';
const Home = () => (<div>首页</div>)
const App = () => (
<Router>
<div>
<Route path={
"/"} component={
Home} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
BrowserHistory
,浏览器的路由就不再通过Hash完成了,而显示正常的路径http://localhost:3000/about
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route} from 'react-router-dom';
const Home = () => (<div>首页</div>)
const App = () => (
<Router>
<div>
<Route path={
"/"} component={
Home} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route,Link} from 'react-router-dom';
const Home = () => (<div>首页</div>)
const About = () => (<div>关于我们</div>)
const App = () => (
<Router>
<div>
<Link to={
"/"} exact={
true} >首页</Link>
---
<Link to={
"/about"} >关于我们</Link>
</div>
{
/* exact={true} 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/about"} component={
About} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
Link
用法一致,稍微有点区别NavLink
可以设置用户的选中样式,Link
不可以import {
BrowserRouter as Router, Route,NavLink} from 'react-router-dom';
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</Link>
---
<NavLink to={
"/about"} >关于我们</Link>
</div>
</Router>
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, NavLink } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页页面</div>)
const App = () => (
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</NavLink>
</div>
{
/* 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, NavLink } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页</div>)
const App = () => (
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</NavLink>
---
<NavLink to={
"/render"}>render</NavLink>
</div>
{
/* 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path="/render" render={
() => <div>render页面</div>} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, NavLink } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页页面</div>)
const App = () => (
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</NavLink>
---
<NavLink to={
"/child"}>children</NavLink>
</div>
{
/* 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
{
/* children 比较特殊,每个页面都会匹配上 */}
<Route path="/child" children={
() => <div>children页面</div>} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
this.props.history.push("/about");
this.props.history.push("/about/888");
props.history.push("/cart?username=lili&age=12");
props.history.push("/login", { kemu: 'html5', time: '1zhou' });
(第二个参数传的是state的值)this.props.history.go(-1);
import React from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, NavLink } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页</div>)
const About = (props) => (
<div>关于我们页面<br/>
接收到的参数:{
props.match.params.userid}
</div>
)
const App = () => (
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</NavLink>
---
<NavLink to={
"/about/666"}>关于我们</NavLink>
</div>
{
/* 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/about/:userid"} component={
About} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React,{
Component} from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, NavLink } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页</div>)
class Cart extends Component {
render() {
console.log(this.props);
return (<div>购物车页面<br/>
{
/* URLSearchParams:解构?号后面的数据 */}
用户ID:{
new URLSearchParams(this.props.location.search).get('id')}<br/>
用户名:{
new URLSearchParams(this.props.location.search).get('name')}
</div>);
}
}
const App = () => (
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</NavLink>
---
<NavLink to={
{
pathname: "/cart", search: "?id=123&name=lili" }}>购物车</NavLink>
</div>
{
/* 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/cart"} component={
Cart} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React,{
Component} from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, NavLink } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页</div>)
class State extends Component {
render() {
console.log(this.props);
return (<div>
state页面<br/>
接收到的参数:{
this.props.location.state.username}
</div>);
}
}
const App = () => (
<Router>
<div>
<NavLink to={
"/"} exact={
true} >首页</NavLink>
---
<NavLink to={
{
pathname: "/state", state: {
"username": "山海经" } }}>state</NavLink>
</div>
{
/* 只完全匹配/ */}
<div>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/state"} component={
State} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
问题:一个路径匹配了多个页面?
Switch 特点:匹配到第一个之后九不再往下匹配了
可以用于处理 404 页面
404页面组件需要放在路由表的最后面
不使用switch
:
import React, {
Component } from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, Link} from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页页面</div>)
class Cart extends Component {
render() {
return (<div>购物车页面</div>);
}
}
const App = () => (
<Router>
<div>
<Link to={
"/"} exact={
true} >首页</Link>
--
<Link to={
{
pathname: "/cart" }}>购物车</Link>
</div>
{
/* exact={true}: 表示只完全匹配/ */}
<div>
{
/* */ }
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/cart"} component={
Cart} />
<Route render={
() => <div>404页面</div>} />
{
/* */}
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
switch
:import React, {
Component } from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, Link, Switch} from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页页面</div>)
class Cart extends Component {
render() {
return (<div>购物车页面</div>);
}
}
const App = () => (
<Router>
<div>
<Link to={
"/"} exact={
true} >首页</Link>
--
<Link to={
{
pathname: "/cart" }}>购物车</Link>
</div>
{
/* exact={true}: 表示只完全匹配/ */}
<div>
<Switch>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/cart"} component={
Cart} />
<Route render={
() => <div>404页面</div>} />
</Switch>
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
exact = {true}
import React, {
Component } from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, Link } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
//需求:center页面中有两个子页面
class Center extends Component {
render() {
return <div>用户中心页面<br/>
<Link to="/center/child1">子页1</Link>
||
<Link to="/center/child2">子页2</Link>
<div className="child">
<Route path="/center/child1" component={
Child1} />
<Route path="/center/child2" component={
Child2} />
</div>
</div>;
}
}
const Child1 = () => (<div>子页 1 页面</div>)
const Child2 = () => (<div>子页 2 页面</div>)
const App = () => (
<Router>
<div>
<Link to={
"/center"} >用户中心</Link>
</div>
<div>
<Route path={
"/center"} component={
Center} />
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React, {
Component } from 'react';
import {
withRouter } from 'react-router-dom';
import "./header.css"
class Header extends Component {
constructor(props) {
super(props);
this.state = {
}
}
goFenlei = () => {
console.log(this);
//Header 是一个组件,他不存在 路由中的history属性
//可以使用 withRouter的高阶组件添加 history属性
this.props.history.push("/about/23");
}
render() {
return (
<div className="header">头部
<button onClick={
this.goFenlei}>点击跳转到关于我们</button>
</div>
);
}
}
export default withRouter(Header);
import React, {
Component } from 'react';
import ReactDOM from 'react-dom';
import {
BrowserRouter as Router, Route, Link, Switch, Redirect, Prompt } from 'react-router-dom';
//BrowserRouter 不带#,NavLink有激活状态链接效果
const Home = () => (<div>首页</div>)
class Center extends Component {
render() {
return (loginType ? <div>用户中心</div> : <Redirect to="/login" />);
}
}
const Login = (props) => (<div>登录</div>)
class Cart extends Component {
render() {
console.log(this.props);
return (<div>购物车页面
<Prompt when={
true} message={
"您确定要离开这个页面么?"} />
</div>);
}
}
let loginType = false;
const App = () => (
<Router>
<div>
<Link to={
"/"} exact={
true} >首页</Link>
--
<Link to={
{
pathname: "/cart" }}>购物车页面</Link>
--
<Link to={
"/center"} >用户中心</Link>
--
<Link to={
"/login"} >登录</Link>
</div>
<div>
<Switch>
<Route path={
"/"} exact={
true} component={
Home} />
<Route path={
"/cart"} component={
Cart} />
<Route path={
"/center"} component={
Center} />
<Route path={
"/login"} component={
Login} />
<Redirect from="/*" to="/" />
{
/* 404页面定位到首页 */}
</Switch>
</div>
</Router>
)
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
上面代码实现的功能:
1. 给购物车页面设置了Prompt 路由后置守卫
2. 当你想离开购物车页面时,会弹出一个确认框
3. 给404页面设置了 Redirect 重定向
4. 当路径不对时,会重新定向到login登录页面
5. 给用户中心页面设置了Redirect 路由前置守卫
6. 当你为登录时,无法打开用户中心,只能跳转到login登录页面先登录
上一篇博客:路由介绍