前言
最近新入职阿里,我们部门用的是 React 全家桶,之前只自学了 React,所以这次要学一下 React-router
使用方法
1 | import { BrowserRouter as Router, Route, Link } from "react-router-dom"; |
Router
这是简单的结构,从第一行开始看,引入了 BrowserRouter
,这个其实还有另外一个兄弟 HashRouter
区别:BrowserRouter
用的是浏览器的HTML5 history API (pushState, replaceState, popstate event),HashRouter
根据URL后面的 #
的内容来进行刷新,这个区别在 Vue-router 里面也有。
联系:都是 React-router 的核心,有 Router 才能继续接下来的工作。
Link
这个组件就相当于 a
标签,当然还有其他类似的组件:<NavLink>
,<Redirect>
,根据不同场景使用
Route
这个组件就是如果匹配到了 path
就会渲染 component
属性对应的组件,注意:如果没有 path
属性,则一定会渲染这个 route,对于 exact
属性,有一张图
可以很清楚的理解 exact
属性
match
这个就是在路由匹配到的时候可以知道匹配的路由里面的东西,具体的属性看下表:
| 属性 | 类型 | 说明/作用 |
| —— | —— | —— |
| params | object | 从 URL 传进来的键值对 |
| isExact | boolean | 是否和 URL 完全匹配 |
| path | string | 值是 path,也就是Route的属性,用作嵌套
| url | string | 值是匹配的 URL,用作嵌套 |
值的注意的一些东西
和
上面说了 <Route>
会根据 path
渲染匹配到路由的组件,而且不设置 path
组件也会渲染,也就是说 <Route>
能够同时渲染多个组件,但是我们有时候只想渲染一个组件,这个时候 <Switch>
就出来了,用法就是在 <Route>
外面包住:1
2
3
4
5
6
7
8import { Switch, Route } from 'react-router'
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
</Switch>
当匹配到一个 route,就会停止接下来的查找,也就是自始自终只有一个组件会被渲染,这在做路由跳转动画的时候会比较有利。
同时渲染侧边栏内容和主页内容
具体场景就是点击侧边栏的内容,在主内容跳转渲染的同时,同时改变侧边栏样式,这里只是简单的版本,具体根据自己需要修改:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
const routes = [
{
path: "/",
exact: true,
sidebar: () => <div>home!</div>,
main: () => <h2>Home</h2>
},
{
path: "/bubblegum",
sidebar: () => <div>bubblegum!</div>,
main: () => <h2>Bubblegum</h2>
},
{
path: "/shoelaces",
sidebar: () => <div>shoelaces!</div>,
main: () => <h2>Shoelaces</h2>
}
];
function SidebarExample() {
return (
<Router>
<div style={{ display: "flex" }}>
<div
style={{
padding: "10px",
width: "40%",
background: "#f0f0f0"
}}
>
<ul style={{ listStyleType: "none", padding: 0 }}>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/bubblegum">Bubblegum</Link>
</li>
<li>
<Link to="/shoelaces">Shoelaces</Link>
</li>
</ul>
{routes.map((route, index) => (
<Route
key={index}
path={route.path}
exact={route.exact}
component={route.sidebar}
/>
))}
</div>
<div style={{ flex: 1, padding: "10px" }}>
{routes.map((route, index) => (
// Render more <Route>s with the same paths as
// above, but different components this time.
<Route
key={index}
path={route.path}
exact={route.exact}
component={route.main}
/>
))}
</div>
</div>
</Router>
);
}
export default SidebarExample;
其实很简单,首先有一个 routes
的配置,在里面设置对应的组件,然后传给 <Route>
,它就会根据传进来的东西生成一个列表,但是真正渲染的只有匹配到路由的那个组件。
withRouter
用法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import React from "react";
import PropTypes from "prop-types";
import { withRouter } from "react-router";
class ShowTheLocation extends React.Component {
static propTypes = {
match: PropTypes.object.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
render() {
const { match, location, history } = this.props;
return <div>You are now at {location.pathname}</div>;
}
}
const ShowTheLocationWithRouter = withRouter(ShowTheLocation);
其实就是通过 withRouter
高阶组件访问 history
对象的属性和最近(UI 结构上靠的最近)的 <Route>
的 match
对象。当组件渲染时,withRouter
会将更新后的 match
、location
和 history
传递给它。