1.前言
使用了React、Vue等开发的应用都是SPA(单页面应用)。
什么是单页面应用呢?
特点:
- 整个应用只有一个完整的页面。
- 店家页面中的链接不会刷新页面,只会做页面的局部更新。
- 数据都需要通过ajax请求获取,并在前端异步展现。
单页面应用想要实现多页面应用类似切换内容效果,那就离不开路由
。
React的路由是一个独立被分割出去的库,在使用路由前需使用下面命令在项目中引入该库:
cnpm install react-router-dom --save
2.路由基础
咋们由浅入深,先来学习最基础的路由使用。
静态路由示例:
index.js:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App.js'
ReactDOM.render(<App />, document.getElementById('root'))
App.js:
import React from 'react'
import {
BrowserRouter as Router, Route, Link } from 'react-router-dom'
import './index.css'
function TakeOut(props) {
return (
<div>
<h3>我是外卖页面</h3>
</div>
)
}
function Order(props) {
return (
<div>
<h3>我是订单页面</h3>
</div>
)
}
function My(props) {
return (
<div>
<h3>我是"我的"页面</h3>
</div>
)
}
export default class App extends React.Component {
render() {
return (
<div>
<h1>哈哈哈,傻瓜</h1>
<Router>
<div className="navigator">
<Link to="/takeout">外卖</Link>
<Link to="/order">订单</Link>
<Link to="/me">我的</Link>
</div>
<div className="container">
<Route path="/takeout" component={
TakeOut}></Route>
<Route path="/order" component={
Order}></Route>
<Route path="/me" component={
My}></Route>
</div>
</Router>
</div>
)
}
}
index.css:
简单的css样式
* {
margin: 0px;
padding: 0px;
}
.navigator {
display: flex;
text-align: center;
}
.navigator a {
flex: 1;
font-size: 20px;
text-decoration: none;
}
.container {
height: 300px;
padding: 50px;
background-color: aqua;
}
结果:
React路由三个重要标签:
-
Router:可以把它看成一个盒子,里面包裹着Route、Link和其它任意标签,注意:
Route、Link必须被包含在Router内部。
-
Route:该标签有两个作用
- 1.该标签使用path、component、render等属性定义路由匹配规则。
- 2.该标签作为占位符,即该标签映射的组件将在该标签的位置上进行展示。
-
Link:本质是一个
a
标签,用于点击实现切换页面组件。
3.如何获取动态路由参数(三种方式)
假设有这么一个需求,一个外卖商家列表,当用户点击某个店铺时,跳转到该店铺详情,那么每个店铺都有一个唯一的id,那么我们才知道用户进入的是哪个店铺,才知道该请求哪个店铺的详情。
3.1 Params参数
通过Params参数也有两种方式获取数据。
1.params方式
:借用useParams库
App.js:
import React from 'react'
import {
BrowserRouter as Router,
Route,
Link,
useParams,
Switch,
} from 'react-router-dom'
import './index.css'
function Child(props) {
let {
id } = useParams()
return <div>{
id}</div>
}
export default class App extends React.Component {
render() {
return (
<div>
<h1>哈哈哈,傻瓜</h1>
<Router>
<div className="navigator">
<Link to="/takeout/123">一品鲜</Link>
<Link to="/takeout/234">牛肉火锅</Link>
<Link to="/takeout/456">糖水</Link>
</div>
<div className="container">
<Route path="/takeout/:id" component={
Child}></Route>
</div>
</Router>
</div>
)
}
}
通过useParams
可以很方便的获取动态路由的参数,得到某个店铺的id之后,就可以请求某个店铺的详情页面了。
2.Params方式:使用组件的props属性
除了使用useParams
可以获取动态路由参数外,也可以使用传入组件的props
获取,先看看props里面包含什么内容:
从图中可以看到,传入组件的props对象包含三个属性,其中match
中的params
就有动态路由的参数,那么我们可以直接使用props.match.params.id
获取参数值。
function Child(props) {
console.log(props)
return <div>{
props.match.params.id}</div>
}
精简总结:
路由链接(携带参数):<Link to=’/demo/test/tom/18’}>详情
注册路由(声明接收):
接收参数:this.props.match.params
3.2 search参数与state参数组合
当路由跳转,需要向组件传递一些非URL的数据时,我们应该怎么传递呢?什么是非URL数据?
看下面URL:
http://localhost:3000/takeout?id=123
这是一个完整的URL,在URL上我们可以获取它的路径/takeout
以及获取id
的查询参数,这些就是在URL上的数据。假如我还想告诉组件一些其它信息,则可以通过下面方式传递参数。
< Link >标签的to
属性设置为一个对象,该对象可有下面这些属性:
- pathname:路径,
pathname:"/takeout"
相当于to="/takeout"
. - search:查询参数,就比如上面URL中的
?id=123
state
:对象类型,可以放入任意传递给组件的数据。
示例:
function Child(props) {
console.log(props)
return <div>{props.location.state.shopName}</div>
}
export default class App extends React.Component {
render() {
return (
<div>
<h1>哈哈哈,傻瓜</h1>
<Router>
<div className="navigator">
<Link
to={
{
pathname: '/takeout',
search: '?id=123',
state: { shopName: '一品鲜' },
}}
>
一品鲜
</Link>
</div>
<div className="container">
<Route path="/takeout" component={Child}></Route>
</div>
</Router>
</div>
)
}
}
这样设置Link,则点击“一品鲜”跳转时,就可以将shopName
数据传递给组件,state可以包含任意多数据。
从打印出来的props
中,location
可以找到我们路由跳转时传递的其它参数。
精简总结:
search参数 路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'}>详情</Link> 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/> 接收参数:this.props.location.search 备注:获取到的search是urlencoded编码字符串,需要借助querystring解析 3.state参数 路由链接(携带参数):<Link to={ {pathname:'/demo/test',state:{name:'tom',age:18}}}>详情</Link> 注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/> 接收参数:this.props.location.state 备注:刷新也可以保留住参数
5. 路由重要属性属性
1.basename
:所有路由的基础路径。
<Router basename="shop">
<div className="navigator">
<Link to="/takeout/123">一品鲜</Link>
<Link to="/takeout/234">牛肉火锅</Link>
<Link to="/takeout/456">糖水</Link>
</div>
<div className="container">
<Route path="/takeout/:id" component={Child}></Route>
</div>
</Router>
2.replace
: 当设置为 true 时,点击链接后将替换历史堆栈中的当前条目,而不是添加新条目。默认为 false。
3.activeClassName
:当元素处于激活状态时应用的类,默认为 active。它将与 className 属性一起使用。(可用于用户点击某路由后,将它设置高亮样式)
4.activeStyle
:对象类型,当元素处于激活状态时应用的样式。
5.exact
:如果为 true,则只有在位置完全匹配时才应用激活类/样式。