目录:
- 对SPA应用的理解
- 对路由的理解
- 前端路由原理
- 路由的基本使用
- 路由组件与一般组件
- NavLink的使用
- 封装NavLink组件
- Switch的使用
- 解决样式丢失问题
- 路由的模糊匹配与严格匹配
- Redirect的使用
- 嵌套路由
- 向路由组件传递params参数
- 向路由组件传递search参数
- .向路由组件传递state参数
- 总结路由参数
- push与repalce
- 编程式路由导航
- withRouter的作用
- BrowserRouter与HashRouter
1.对SPA应用的理解
- 单页Web应用(single page web application,SPA)。
- 整个应用只有一个完整的页面。
- 点击页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都需要通过ajax请求获取, 并在前端异步展现。
2.对路由的理解
什么是路由?
- 一个路由就是一个映射关系(key:value)
- key为路径, value可能是function或component
路由分类
- 后端路由:
- 理解: value是function, 用来处理客户端提交的请求。
- 注册路由: router.get(path, function(req, res))
- 工作过程:当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
- 前端路由:
- 浏览器端路由,value是component,用于展示页面内容。
- 注册路由: <Route path="/test" component={Test}>
- 工作过程:当浏览器的path变为/test时, 当前路由组件就会变为Test组件
3.前端路由原理
前端路由的基石.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端路由的基石_history</title>
</head>
<body>
<a href="http://www.atguigu.com" onclick="return push('/test1') ">push test1</a><br><br>
<button onClick="push('/test2')">push test2</button><br><br>
<button onClick="replace('/test3')">replace test3</button><br><br>
<button onClick="back()"><= 回退</button>
<button onClick="forword()">前进 =></button>
<script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
<script type="text/javascript">
// let history = History.createBrowserHistory() //方法一,直接使用H5推出的history身上的API
let history = History.createHashHistory() //方法二,hash值(锚点)
function push (path) {
history.push(path)
return false
}
function replace (path) {
history.replace(path)
}
function back() {
history.goBack()
}
function forword() {
history.goForward()
}
history.listen((location) => {
console.log('请求路由路径变化了', location)
})
</script>
</body>
</html>
4.路由的基本使用
- 明确好界面中的导航区、展示区
- 导航区的a标签改为Link标签 <Link to="/xxxxx" >Demo</Link>
- 展示区写Route标签进行路径的匹配<Route path='/xxxx 'component={Demo}/>
- <App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>
App.js
import React, {Component} from 'react';
import {Link, Route} from "react-router-dom";
import About from "./components/About/About";
import Home from "./components/Home/Home";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<Link className="list-group-item" to="/about">About</Link>
<Link className="list-group-item" to="/home">Home</Link>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
About.jsx
import React, {Component} from 'react';
class About extends Component {
render() {
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
}
export default About;
Home.jsx
import React, {Component} from 'react';
class Home extends Component {
render() {
return (
<div>
<h3>我是Home的内容</h3>
</div>
);
}
}
export default Home;
运行结果:
5.路由组件与一般组件
- 写法不同:
- 一般组件: <Demo/ >
- 路由组件: <Route path="/demo" component={Demo}/>
- 存放位置不同:
- 一般组件:components
- 路由组件: pages
- 接收到的props不同:
- 一般组件:,写组件标签时传递了什么,就能收到什么
- 路由组件:接收到三个固定的属性
- history:
- go: f go(n)
- goBack: f goBack()
- goForward: f goForward()
- push: f push(path,state)
- replace: f replace(path, state)
-
location:
- pathname: "/about"
- search: ""
- state: undefined
-
match:|
- params: {}
- path: "/about"
- url: "/about"
- history:
6.NavLink的使用
Header.jsx
import React, {Component} from 'react';
class Header extends Component {
render() {
// console.log('Header组件收到的props是', this.props)
return (
<div>
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
);
}
}
export default Header;
About.jsx
import React, {Component} from 'react';
class About extends Component {
render() {
// console.log('About组件收到的props是', this.props)
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
}
export default About;
Home.jsx
import React, {Component} from 'react';
class Home extends Component {
render() {
return (
<div>
<h3>我是Home的内容</h3>
</div>
);
}
}
export default Home;
App.js
import React, {Component} from 'react';
import {NavLink, Route} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink activeClassName="atguigu" className="list-group-item" to="/about">About</NavLink>
<NavLink activeClassName="atguigu" className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="theme-color" content="#000000"/>
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png"/>
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"/>
<link rel="stylesheet" href="css/bootstrap.css">
<style>
.atguigu {
background-color: orange !important;
color: white !important;
}
</style>
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
项目结构:
运行结果:
7.封装NavLink组件
NavLink与封装NavLink
- NavLink可以实现路由链接的高亮,通过activeclassName指定样式名
- 标签体内容是一个特殊的标签属性
- 通过this.props.children可以获取标签体内容
App.js
import React, {Component} from 'react';
import {NavLink, Route} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<MyNavLink to="/about" a={1} b={2} c={3}>About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
Header.jsx
import React, {Component} from 'react';
class Header extends Component {
render() {
// console.log('Header组件收到的props是', this.props)
return (
<div>
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
);
}
}
export default Header;
MyNavLink.jsx
import React, {Component} from 'react';
import {NavLink} from "react-router-dom";
class MyNavLink extends Component {
render() {
console.log(this.props)
return (
<div>
<NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
</div>
);
}
}
export default MyNavLink;
About.jsx
import React, {Component} from 'react';
class About extends Component {
render() {
// console.log('About组件收到的props是', this.props)
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
}
export default About;
Home.jsx
import React, {Component} from 'react';
class Home extends Component {
render() {
return (
<div>
<h3>我是Home的内容</h3>
</div>
);
}
}
export default Home;
项目结构:
运行结果:
8.Switch的使用
- 通常情况下,path和component是一一对应的关系。
- Switch可以提高路由匹配效率(单一匹配)。
Test.jsx
import React, {Component} from 'react';
class Test extends Component {
render() {
return (
<div>
<h2>Test...</h2>
</div>
);
}
}
export default Test;
App.js
import React, {Component} from 'react';
import {NavLink, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
import Test from "./pages/Test/Test";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<MyNavLink to="/about" a={1} b={2} c={3}>About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
<Route path="/home" component={Test}></Route>
</Switch>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
运行结果:
项目结构:
9.解决样式丢失问题
-
public/index.html 中引入样式时不写./写/(常用)
-
public/index.html 中引入样式时不写﹒/写%PUBLIC_URL%(常用)
-
使用HashRouter
1../css/bootstrap.css改为:
<link rel="stylesheet" href="css/bootstrap.css">
2../css/bootstrap.css改为:
<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">
3.BroserRouter改成HashRouter
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter, HashRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<HashRouter>
<App/>
</HashRouter>
);
10.路由的模糊匹配与严格匹配
- 默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
- 开启严格匹配:<Route exact={true} path="/about" component={About}/>
- 严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
App.js
import React, {Component} from 'react';
import {Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home/a/b">Home</MyNavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Switch>
<Route exact path="/about" component={About}></Route>
<Route exact path="/home" component={Home}></Route>
</Switch>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
运行结果:
11.Redirect的使用
- 一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
- 具体编码:
<Switch> <Route path="/about" component={About}/> <Route path="/home" component={Home}/> <Redirect to="/about"/> </Switch>
App.js
import React, {Component} from 'react';
import {Redirect, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
<Redirect to="/about"></Redirect>
</Switch>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
12.嵌套路由
- 注册子路由时要写上父路由的path值
- 路由的匹配是按照注册路由的顺序进行的
App.js
import React, {Component} from 'react';
import {Redirect, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
<Redirect to="/about"></Redirect>
</Switch>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
Message.jsx
import React, {Component} from 'react';
class Message extends Component {
render() {
return (
<div>
<ul>
<li>
<a href="/message1">message001</a>
</li>
<li>
<a href="/message2">message002</a>
</li>
<li>
<a href="/message/3">message003</a>
</li>
</ul>
</div>
);
}
}
export default Message;
News.jsx
import React, {Component} from 'react';
class News extends Component {
render() {
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
}
export default News;
Home.jsx
import React, {Component} from 'react';
import MyNavLink from "../../components/MyNavLink/MyNavLink";
import {Redirect, Route, Switch} from "react-router-dom";
import News from "./News/News";
import Message from "./Message/Message";
class Home extends Component {
render() {
return (
<div>
<h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<MyNavLink to="/home/news">News</MyNavLink>
</li>
<li>
<MyNavLink to="/home/message">Message</MyNavLink>
</li>
</ul>
<Switch>
<Route path="/home/news" component={News}></Route>
<Route path="/home/message" component={Message}></Route>
<Redirect to="/home/news"></Redirect>
</Switch>
</div>
</div>
);
}
}
export default Home;
MyNavLink.jsx
import React, {Component} from 'react';
import {NavLink} from "react-router-dom";
class MyNavLink extends Component {
render() {
console.log(this.props)
return (
<div>
<NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
</div>
);
}
}
export default MyNavLink;
Header.jsx
import React, {Component} from 'react';
class Header extends Component {
render() {
// console.log('Header组件收到的props是', this.props)
return (
<div>
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
);
}
}
export default Header;
About.jsx
import React, {Component} from 'react';
class About extends Component {
render() {
// console.log('About组件收到的props是', this.props)
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
}
export default About;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter, HashRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<HashRouter>
<App/>
</HashRouter>
);
项目结构:
运行结果:
13. 向路由组件传递params参数
1.params参数
- 路由链接(携带参数):<Link to='/demo/test/tom/18'}>详情</Link>
- 注册路由(声明接收):<Route path="/demo/test/:name/:age" component={Test}/>
- 接收参数: const {id,title} = this.props.match.params
Header.jsx
import React, {Component} from 'react';
class Header extends Component {
render() {
// console.log('Header组件收到的props是', this.props)
return (
<div>
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
);
}
}
export default Header;
MyNavLink.jsx
import React, {Component} from 'react';
import {NavLink} from "react-router-dom";
class MyNavLink extends Component {
render() {
console.log(this.props)
return (
<div>
<NavLink activeClassName="atguigu" className="list-group-item" {...this.props}/>
</div>
);
}
}
export default MyNavLink;
About.jsx
import React, {Component} from 'react';
class About extends Component {
render() {
// console.log('About组件收到的props是', this.props)
return (
<div>
<h3>我是About的内容</h3>
</div>
);
}
}
export default About;
Detail.jsx
import React, {Component} from 'react';
const DetailData = [
{id: '01', content: '你好,中国'},
{id: '02', content: '你好,尚硅谷'},
{id: '03', content: '你好,未来的自己'},
]
class Detail extends Component {
render() {
// console.log(this.props)
const {id, title} = this.props.match.params
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id
})
return (
<ul>
<li>ID:{id}</li>
<li>TITLE:{title}</li>
<li>CONTENT:{findResult.content}</li>
</ul>
);
}
}
export default Detail;
Message.jsx
import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";
class Message extends Component {
state = {
messageArr: [
{id: '01', title: '消息1'},
{id: '02', title: '消息2'},
{id: '03', title: '消息3'},
]
}
render() {
const {messageArr} = this.state
return (
<div>
<ul>
{
messageArr.map((msgObj) => {
return (
<li key={msgObj.id}>
<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
<Route path="/home/message/detail/:id/:title" component={Detail}></Route>
</div>
);
}
}
export default Message;
News.jsx
import React, {Component} from 'react';
class News extends Component {
render() {
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
}
export default News;
Home.jsx
import React, {Component} from 'react';
import MyNavLink from "../../components/MyNavLink/MyNavLink";
import {Redirect, Route, Switch} from "react-router-dom";
import News from "./News/News";
import Message from "./Message/Message";
class Home extends Component {
render() {
return (
<div>
<h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<MyNavLink to="/home/news">News</MyNavLink>
</li>
<li>
<MyNavLink to="/home/message">Message</MyNavLink>
</li>
</ul>
<Switch>
<Route path="/home/news" component={News}></Route>
<Route path="/home/message" component={Message}></Route>
<Redirect to="/home/news"></Redirect>
</Switch>
</div>
</div>
);
}
}
export default Home;
App.js
import React, {Component} from 'react';
import {Redirect, Route, Switch} from "react-router-dom";
import About from "./pages/About/About";
import Home from "./pages/Home/Home";
import Header from "./components/Header/Header";
import MyNavLink from "./components/MyNavLink/MyNavLink";
class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<Header a={1}></Header>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
<Redirect to="/about"></Redirect>
</Switch>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import {BrowserRouter, HashRouter} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<HashRouter>
<App/>
</HashRouter>
);
运行结果:
项目结构:
14.向路由组件传递search参数
2.search参数
- 路由链接(携带参数): <Link to=' /demo/test?name=tom&age=18'}>详情</Link>
- 注册路由(无需声明,正常注册即可): <Route path="/demo/test" component={Test}/>
- 接收参数: const isearch} = this.props.location
- 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析
Message.jsx
import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";
class Message extends Component {
state = {
messageArr: [
{id: '01', title: '消息1'},
{id: '02', title: '消息2'},
{id: '03', title: '消息3'},
]
}
render() {
const {messageArr} = this.state
return (
<div>
<ul>
{
messageArr.map((msgObj) => {
return (
<li key={msgObj.id}>
{/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
{/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
<Route path="/home/message/detail" component={Detail}></Route>
</div>
);
}
}
export default Message;
Detail.jsx
import React, {Component} from 'react';
import qs from "qs"
const DetailData = [
{id: '01', content: '你好,中国'},
{id: '02', content: '你好,尚硅谷'},
{id: '03', content: '你好,未来的自己'},
]
class Detail extends Component {
render() {
console.log(this.props)
// const {id, title} = this.props.match.params
const {search} = this.props.location
const {id, title} = qs.parse(search.slice(1))
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id
})
return (
<ul>
<li>ID:{id}</li>
<li>TITLE:{title}</li>
<li>CONTENT:{findResult.content}</li>
</ul>
);
}
}
export default Detail;
运行结果:
项目结构:
15.向路由组件传递state参数
state参数:
- 路由链接(携带参数): <Link to={{path:' /demo/test',state:{name : ' tom' ,age:18]}}>详情</Link>注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
- 接收参数: this.props.location.state
- 备注:刷新也可以保留住参数
Message.jsx
import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";
class Message extends Component {
state = {
messageArr: [
{id: '01', title: '消息1'},
{id: '02', title: '消息2'},
{id: '03', title: '消息3'},
]
}
render() {
const {messageArr} = this.state
return (
<div>
<ul>
{
messageArr.map((msgObj) => {
return (
<li key={msgObj.id}>
{/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
{/*<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>*/}
<Link to={{
pathname: '/home/message/detail',
state: {id: msgObj.id, title: msgObj.title}
}}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
{/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
{/*<Route path="/home/message/detail" component={Detail}></Route>*/}
<Route path="/home/message/detail" component={Detail}></Route>
</div>
);
}
}
export default Message;
Detail.jsx
import React, {Component} from 'react';
import qs from "qs"
const DetailData = [
{id: '01', content: '你好,中国'},
{id: '02', content: '你好,尚硅谷'},
{id: '03', content: '你好,未来的自己'},
]
class Detail extends Component {
render() {
console.log(this.props)
// const {id, title} = this.props.match.params
// const {search} = this.props.location
// const {id, title} = qs.parse(search.slice(1))
const {id, title} = this.props.location.state || {}
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id
}) || {}
return (
<ul>
<li>ID:{id}</li>
<li>TITLE:{title}</li>
<li>CONTENT:{findResult.content}</li>
</ul>
);
}
}
export default Detail;
运行结果:
16.总结路由参数
17.push与repalce
Message.jsx
import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";
class Message extends Component {
state = {
messageArr: [
{id: '01', title: '消息1'},
{id: '02', title: '消息2'},
{id: '03', title: '消息3'},
]
}
render() {
const {messageArr} = this.state
return (
<div>
<ul>
{
messageArr.map((msgObj) => {
return (
<li key={msgObj.id}>
{/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
{/*<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>*/}
<Link replace={true} to={{
pathname: '/home/message/detail',
state: {id: msgObj.id, title: msgObj.title}
}}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
{/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
{/*<Route path="/home/message/detail" component={Detail}></Route>*/}
<Route path="/home/message/detail" component={Detail}></Route>
</div>
);
}
}
export default Message;
- push:留下记录
- repalce:不留记录
18.编程式路由导航
Message.jsx
import React, {Component} from 'react';
import Detail from "./Detail/Detail";
import {Link, Route} from "react-router-dom";
class Message extends Component {
state = {
messageArr: [
{id: '01', title: '消息1'},
{id: '02', title: '消息2'},
{id: '03', title: '消息3'},
]
}
render() {
const {messageArr} = this.state
return (
<div>
<ul>
{
messageArr.map((msgObj) => {
return (
<li key={msgObj.id}>
{/*<Link to={`/home/message/detail/${msgObj.id}/${msgObj.title}`}>{msgObj.title}</Link>*/}
{/*<Link to={`/home/message/detail/?id=${msgObj.id}&title=${msgObj.title}`}>{msgObj.title}</Link>*/}
<Link replace={true} to={{
pathname: '/home/message/detail',
state: {id: msgObj.id, title: msgObj.title}
}}>{msgObj.title}</Link>
</li>
)
})
}
</ul>
<hr></hr>
{/*<Route path="/home/message/detail/:id/:title" component={Detail}></Route>*/}
{/*<Route path="/home/message/detail" component={Detail}></Route>*/}
<Route path="/home/message/detail" component={Detail}></Route>
</div>
);
}
}
export default Message;
Detail.jsx
import React, {Component} from 'react';
import qs from "qs"
const DetailData = [
{id: '01', content: '你好,中国'},
{id: '02', content: '你好,尚硅谷'},
{id: '03', content: '你好,未来的自己'},
]
class Detail extends Component {
render() {
console.log(this.props)
// const {id, title} = this.props.match.params
// const {search} = this.props.location
// const {id, title} = qs.parse(search.slice(1))
const {id, title} = this.props.location.state || {}
const findResult = DetailData.find((detailObj) => {
return detailObj.id === id
}) || {}
return (
<ul>
<li>ID:{id}</li>
<li>TITLE:{title}</li>
<li>CONTENT:{findResult.content}</li>
</ul>
);
}
}
export default Detail;
19.withRouter的作用
News.jsx
import React, {Component} from 'react';
class News extends Component {
componentDidMount() {
setTimeout(() => {
this.props.history.push('/home/message')
}, 2000)
}
render() {
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
}
export default News;
- 借助this.prosp.history对象上的API对操作路由跳转、前进、后退
- this.prosp.history.push()
- this.prosp.history.replace()
- this.prosp.history.goBack()
- this.prosp.history.goForward()
- this.prosp.history.go()
- withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
- withRouter的返回值是一个新组件
Header.jsx
import React, {Component} from 'react';
import {withRouter} from "react-router-dom";
class Header extends Component {
back = () => {
this.props.history.goBack()
}
forward = () => {
this.props.history.goForward()
}
go = () => {
this.props.history.go(2)
}
render() {
// console.log('Header组件收到的props是', this.props)
return (
<div>
<div className="page-header">
<h2>React Router Demo</h2>
<button onClick={this.back}>回退</button>
<button onClick={this.forward}>前进</button>
<button onClick={this.go}>go</button>
</div>
</div>
);
}
}
export default withRouter(Header);
20.BrowserRouter与HashRouter
- 1.底层原理不一样:
- BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
- HashRouter使用的是URL的哈希值
- 2.path表现形式不一样
- BrowserRouter的路径中没有#,例如: localhost:3000/demo/test
- HashRouter的路径包含#,例如: localhost:3000/#/demo/test
- 3.刷新后对路由state参数的影响
- (1).BrowserRouter没有任何影响,因为state保存在history对象中。
- (2).HashRouter刷新后会导致路由state参数的丢失。
- 4.备注: HashRouter可以用于解决一些路径错误相关的问题。