React-Router作为React体系的一个重要部分,是一个路由库。其可管理URL,实现组件的切换和状态的变换。
1.单页面应用
单页面得特点:只需要加载一次主页面,通过局部刷新,就可以实现跳转或者切换页面。 优点:加载速度快,用户体验比较好。 缺点: - 第一次加载比传统要慢一点 - 不利seo - 页面相对复杂 - 返回键
2.HashRouter和BrowserRouter
HashRouter:在路径中包含了#,相当于HTML的锚点定位。(# 符号的英文叫hash,所以叫HashRouter) 。HashRouter不能(除非手动拼接URL字符串),因此一般配合Redux使用,实现组件间的数据通信。
BrowserRouter:使用的是HTML5的新特性History,没有HashRouter(锚点定位)那样通用,低版本浏览器可能不支持。BrowserRouter进行组件跳转时可以传递任意参数实现组件间的通信。
注意:当使用HashRouter把APP根组件的元素包裹起来之后,网站就已经启用路由了,在一个HashRouter中,只能有唯一的一个根元素。 在一个网站中,只需要使用唯一的一次
3.Route和Link
Route: Route表示一个路由规则,在Route上,有两个比较重要的属性,path,component。Route创建的标签,就是路由规则,其中path表示要匹配的路由,component表示要展示的组件。Route具有两种身份:1.它是一个路由匹配规则;2.它是一个占位符,表示将来匹配到的组件都放到这个位置
Link: Link表示一个路由的链接,属性to,to属性的地址也是/开头,Link在页面渲染的是a标签。
注意: - Route 组件path地址是以/开头 ,配置component属性,是显示的组件,这个属性不可以大写。 - Route组件可以单双标签使用,单标签需要/结尾,双标签不可以在中间写入别的东西。
4.路由传值
通过配置路由的地址,在Link跳转时: - Route path路径后面 /:id (key) - Link to 路径后面 /top/10 (value)
接收传值: - class类组件,this.props.match.params.属性名 - 函数组件:形参.match.params.属性名
5.嵌套路由
嵌套路由:在路由组件中,使用Link, Route,配置子路由,实现跳转,切换;下面为一级路由,在一级路由Home为路由组件。
<Route path="/home" component={ Home }></Route>
在Home组件中继续使用Link,Route进行路由的嵌套,需要注意的就是路由地址,前部分为一级路由地址,后面接一个二级路由相应的路径。
render() {
return (
<div>
<ul>
<li><Link to="/home/a">推荐</Link></li>
<li><Link to="/home/b">新时代</Link></li>
<li><Link to="/home/c">动漫</Link></li>
</ul>
<Route path="/home/a" component={ A }></Route>
<Route path="/home/b" component={ B }></Route>
<Route path="/home/c" component={ C }></Route>
</div>
)
}
6.NavLink
NavLink带有选中activeClassName ,如果路由处于激活状态,显示激活class样式。NavLink增加了一个activeClassName属性绑定一个class类样式,这时在触发NavLink时,会触发相应得样式,这样有一个切换效果。
7.重定向
Redirect 重定向 具备to属性,可以直接跳转到指定路由。在render方法中,使用内置组件,Redirect内置组件使用to属性,当执行到内置标签时,会进行to跳转路由,to后面接的地址是什么,就可以匹配到相应得路由组件。例如:
<Redirect to="/home/c"></Redirect>
8.Switch
Switch 具有排他性,在组件中使用Switch标签包裹所有得Route,这时,Route相当于每一个path都是精准的匹配,展示相应的组件,最后一个Route是一个不具备地址的路由路径,如果当Link指向一个不存在的地址时,没有精准的匹配到地址,那么会显示到C404路由,使用Switch只会显示一个组件,匹配到为止。
<Switch>
<Route path="/home" component={ Home }></Route>
<Route path="/video" component={ Video}></Route>
<Route path="/book" component={ Book }></Route>
<Route path="/news" component={ News }></Route>
<Route path="/user" component={ User }></Route>
<Route component={ C404 }></Route>
</Switch>
综合案例
项目结构图如下:

package.json 依赖如下:
"devDependencies": {
"@babel/core": "^7.18.5",
"@babel/plugin-transform-runtime": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"@babel/preset-react": "^7.17.12",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^4.0.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.1",
"sass": "^1.52.3",
"sass-loader": "^13.0.0",
"style-loader": "^3.3.1",
"terser-webpack-plugin": "^5.3.3",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.2",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"@babel/runtime": "^7.18.3",
"axios": "^0.27.2",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"react-router-dom": "^5.2.1"
}
src/style.css
.red{
color: lightsalmon;
}
src/About.js
import React, { Component } from 'react'
export default class About extends Component {
render() {
return (
<div>
关于我们
</div>
)
}
}
src/Goods.js
import React, { Component } from 'react'
export default class Goods extends Component {
render() {
console.log(this.props)
return (
<div>
产品中心
</div>
)
}
}
src/Home.js
import React, { Component } from 'react'
export default class Home extends Component {
render() {
return (
<div>
网站首页
</div>
)
}
}
src/News.js
import React, { Component } from 'react'
export default class News extends Component {
//代码优化
constructor(props){
super();
this.state = {
routeParams:props.match.params
}
}
render() {
//console.log(this.props)
//let {cid,nid} = this.props.match.params
return (
<div>
{/*新闻中心 -- {cid},{nid}*/}
新闻中心--{this.state.routeParams.cid},{this.state.routeParams.nid}
</div>
)
}
}
src/Search.js
import React, { Component } from 'react'
export default class Search extends Component {
render() {
return (
<div>
搜索页面
</div>
)
}
}
src/Main.js
import React, { Component } from 'react'
import { Link, Route, Switch,NavLink } from 'react-router-dom'
import About from './About'
import Goods from './Goods'
import Home from './Home'
import News from './News'
import Search from "./Search";
import "./style.css";
export default class Main extends Component {
render() {
return (
<div>
<NavLink activeClassName="red" to="/home">首页</NavLink>
<NavLink activeClassName="red" to="/classify/1/news/12">新闻</NavLink>
<NavLink activeClassName="red" to="/goods?id=11">产品</NavLink>
<NavLink activeClassName="red" to="/about">关于</NavLink>
<NavLink activeClassName="red" to="/search">搜索</NavLink>
<button onClick={this.goto.bind(this)}>详情</button>
<hr></hr>
<Switch>
{/* 动态路由 */}
<Route path="/classify/:cid/news/:nid" component={News} />
<Route path="/goods" component={Goods} />
<Route path="/about" component={About} />
<Route path="/search" component={Search}/>
<Route path="/home" component={Home} />
</Switch>
</div>
)
}
goto(){
// window.location.hash = '/details'
// this.props.history.push({
// pathname: '/details',
// state: {
// id: 12
// }
// })
this.props.history.push({
pathname: '/details',
news: {
id: 12,
title: '新闻标题',
createTime: '2021-1-1'
}
})
}
}
src/Login.js
import React, { Component } from 'react'
export default class Login extends Component {
render() {
return (
<div>
登录页面
</div>
)
}
}
src/Details.js
import React, { Component } from 'react'
import { Redirect } from 'react-router'
export default class Details extends Component {
state = {
news: {}
}
componentWillMount(){
// this.state.news = this.props.history.location.news
}
render() {
console.log(this.props)
return (
<div>
{this.isLogin()}
{/* <p>{this.state.news.title}</p> */}
{/* <Redirect to="/login"></Redirect> */}
</div>
)
}
isLogin(){
let user
if(user){
return (
<p>新闻详情</p>
)
}else{
return <Redirect to="/login"></Redirect>
}
}
componentDidMount(){
// this.state.news = this.props.history.location.news
}
}
src/App.js
import React, {Component} from 'react'
import {BrowserRouter, HashRouter, Route, Switch} from 'react-router-dom'
import Details from './Details'
import Login from './Login'
import Main from './Main'
export default class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/login" component={Login}/>
<Route path="/details" component={Details}/>
<Route path="/" component={Main}/>
</Switch>
</BrowserRouter>
)
}
}
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'
ReactDOM.render(<App />,document.getElementById('root'));
运行效果:
