基本用法
-
安装依赖:
npm i -S react-router-dom
-
使用时,路由器
Router
就是React
的一个组件。 -
Router
组件本身只是一个容器,真正的路由要通过Route
组件定义。
path 属性
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')
);
- 当地址为
http://localhost:3000/main
,页面会加载首页组件
- 当地址为
http://localhost:3000/about
,页面会加载关于我们组件
如果不写,那么不管路径是否匹配,总是会加载所有组件。
<Router>
<div>
<Route component={
Home} />
<Route component={
About} />
</div>
</Router>
Histroy 属性
- 用来监听浏览器地址栏的变化,并将URL解析成一个地址对象
HashRouter
- 如果设为
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')
);
BrowserRouter
- 如果设为
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')
);
声明式跳转
Link
Link
组件用于取代<a>
元素,生成一个链接,允许用户点击后跳转到另一个路由。- 算是
<a>
元素的React 版本,可以接收Router的状态
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')
);
NavLink
- 与
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>
路由组件
- Route 设置 路由对应的组件有 3 种形式:
component
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')
);
render
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')
);
children
- children 比较特殊,每个页面都会匹配上
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')
);
编程式导航
- 实现 js 中的页面跳转
push
- 不传参:
this.props.history.push("/about");
- 传 params:
this.props.history.push("/about/888");
- 传 search:
props.history.push("/cart?username=lili&age=12");
- 传 state:
props.history.push("/login", { kemu: 'html5', time: '1zhou' });
(第二个参数传的是state的值)
go
- 表示回退或前进多少页, -1 表示上一页
this.props.history.go(-1);
路由传参
- 路由传参有三种方式
match.params
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')
);
location.search
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')
);
location.state
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页面处理
-
问题:一个路径匹配了多个页面?
-
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>
{
/* <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')
);
- 使用
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')
);
withRouter添加路由属性
- withRouter 可以给普通的组件添加路由属性
- 一般用在头部,尾部,withRouter 用法是高阶组件
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);
路由守卫
- Redirect 重定向 ,可以做路由前置守卫
- Prompt 路由后置守卫
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登录页面先登录
上一篇博客:路由介绍
转载:https://blog.csdn.net/qq_45677671/article/details/116168250
查看评论