RCT006 React Route
Tags: react
Published: 2020-12-22 09:20:22

# React路由

路由就是可以根据url来使react渲染标签，比如url是`/login`就渲染`<Login / >`标签，是`/home`就渲染`<Home />`标签。

# react-router-dom

react-router-dom是 React 的实现路由功能的**组件**。

## 安装

```
npm install react-router-dom --save
```

## 基本路由

1. 在src目录下新建pages文件夹用于存储页面
2. 在pages内新建几个页面（实际上每个页面就是一个react组件）
3. 在src目录下新建文件route.js

### BrowserRouter / HashRouter

HashRouter 会在url后面自动加上"#"。会加载所有匹配到的内容。

### Switch

Switch是react 4.0的新特性，只要找到能够匹配的路由，就会停止匹配。

### Link/NavLink

相当于`<a>`标签，路由封装。

## 基本路由部分的代码

route.js
```javascript
// import {BrowserRouter as Router,Route,Switch} from "react-router-dom";
import { HashRouter as Router, Route, Switch } from "react-router-dom";
import React from 'react'
import Contact from "./pages/contact";
import Login from "./pages/login";
import Home from "./pages/home";
import NoMatch from "./pages/404";

export default function MyRouter() {
  return <Router>
    {/*普通方式，根据path匹配，会加载所有匹配到的内容，浏览器输入'/login'会加载Home和Login元素*/}
    {/*<Route path = "/" component={Home}></Route>*/}
    {/*<Route path = "/login" component={Login}></Route>*/}
    {/*<Route path = "/contact" component={Contact}></Route>*/}

    {/*如果用switch，浏览器输入'/login'也只会加载Home元素，因为'/login'先匹配了'/'*/}
    {/*<Route>标签内加入 exact 可以精准匹配 */}
    {/*如果导入的是HashRouter，会自动加上# 如 http://localhost:3000/login#/ */}
    <Switch>
      <Route exact path="/" component={Home}></Route>
      <Route path="/login" component={Login}></Route>
      <Route path="/contact" component={Contact}></Route>
      <Route path="*" component={NoMatch}></Route>
    </Switch>

  </Router>
}

```

index.js
```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import MyRouter from './route.js';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <MyRouter/>
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

home.js
```javascript
import React from 'react'
import {Link} from "react-router-dom";

export default function Home() {
    return (
      <div>
        <h1>Welcome to Cheap as Chips Cleaning</h1>
        {/* just like <a> */}
        <Link to="/login">Sign In</Link> 
        <br/>
        <Link to="/contact">Contact Us</Link>
        <br/>
      </div>
    )
}
```

## 动态路由

实际上就是在路由的url里面加入参数。比如我们加一个profile页面（用class组件编写），从url中传入用户的id。

## 动态路由部分的代码

route.js
```javascript
<Switch>
  <Route exact path="/" component={Home}></Route>
  <Route path="/login" component={Login}></Route>
  <Route path = "/contact" component={Contact}></Route>
  <Route path="/profile/:userId" component={Profile}></Route>
  <Route path="*" component={NoMatch}></Route>
</Switch>
```

profile.js
```javascript
import React from 'react'

export default class Profile extends React.Component {
  jumpHome = () => {
    this.props.history.push('/')
  }

  render() {
    return <div>
      <h1>this is detail</h1>
      {/* 获取路由参数 */}
      <p>当前的参数值为：{this.props.match.params.userId}</p>
      <button onClick={this.jumpHome}>Home</button>
    </div>
  }
}
```

如果要使用函数组件来获得参数，则需要引入Hooks。这将会在下一节中介绍。