react-router(v4)

概要

开发单页应用, 首先绕不开的内容就是路由, react router v4 版本是最新的版本. 和之前的版本相比, 成熟了很多, 也简单了很多, 使用起来更加方便.

核心 component

react-router V4 可以用于 Web 和 Native. 这里主要讨论基于 Web 的应用.

react-router 有很多 Components, 但是只要掌握下面 3 个 Component 就可以管理好 react 应用的路由了.

Router component

Router 是整个应用的路由. 在 Web 应用中, 使用 BrowerRouter 来包装 App

<BrowserRouter>
  <App />
</BrowserRouter>

然后, 在 App component 中, 就可以使用 Route 来定义各个路由对应的 component

Route component

每个 Route 都是一个具体的路由, 对应一个具体的页面. Route 可以对应一个 Component, 也可以直接写个匿名的 render 函数.

Route 中最常用的属性就是 path, 也就是路由的地址, 除此之外, Route 最重要的作用是会将 { match, location, history } 3 个属性注入到对应的 Component 或者 render 函数中.

Link 是用来导航的, 也就是在不同 Route 之间切换就会用到 Link.

常用路由示例

示例工程

示例工程的创建采用 create-react-app 工具.

$ create-react-app route-test
$ cd route-test
$ yarn add react-router-dom

基本使用

修改工程中的 App.js 文件, 增加 route 的 sample

import React, { Component } from 'react'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import './App.css'

const Index = () => <h2>Home</h2>
const About = () => <h2>About</h2>
const Users = () => <h2>Users</h2>

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <nav>
            <ul>
              <li>
                <Link to="/">Home</Link>
              </li>
              <li>
                <Link to="/about/">About</Link>
              </li>
              <li>
                <Link to="/users/">Users</Link>
              </li>
            </ul>
          </nav>

          <Route path="/" exact component={Index} />
          <Route path="/about/" component={About} />
          <Route path="/users/" component={Users} />
        </div>
      </Router>
    )
  }
}

export default App

这个示例中, 就包含了 3 个常用组件 Router, Route 和 Link

路由参数

路由的参数可以加在 path 上, 下面的示例中, Users Component 可以通过注入的 match 来得到 URL 中的参数.

import React, { Component } from 'react'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import './App.css'

const Index = () => <h2>Home</h2>
const About = () => <h2>About</h2>
const Users = ({ match }) => (
  <h2>
    User is {match.params.name}, age: {match.params.age}
  </h2>
)

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <nav>
            <ul>
              <li>
                <Link to="/">Home</Link>
              </li>
              <li>
                <Link to="/about/">About</Link>
              </li>
              <li>
                <Link to="/users/test/16">Users</Link>
              </li>
            </ul>
          </nav>

          <Route path="/" exact component={Index} />
          <Route path="/about/" component={About} />
          <Route path="/users/:name/:age" component={Users} />
        </div>
      </Router>
    )
  }
}

export default App

query 参数

除了上面那种 RESTful 的参数方式, 也可以通过 query 来传递参数. 下例中, 通过 location.search 来获取 querystring, 至于解析 querystring, 已有很多现成的方法可以使用.

import React, { Component } from 'react'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import './App.css'

const Index = () => <h2>Home</h2>
const About = ({ match, location }) => (
  <h2>About's search string: {location.search}</h2>
)
const Users = ({ match }) => (
  <h2>
    User is {match.params.name}, age: {match.params.age}
  </h2>
)

class App extends Component {
  render() {
    return (
      <Router>
        <div>
          <nav>
            <ul>
              <li>
                <Link to="/">Home</Link>
              </li>
              <li>
                <Link to={{ pathname: '/about/', search: '?name=test&age=16' }}>
                  About
                </Link>
              </li>
              <li>
                <Link to="/users/test/16">Users</Link>
              </li>
            </ul>
          </nav>

          <Route path="/" exact component={Index} />
          <Route path="/about/" component={About} />
          <Route path="/users/:name/:age" component={Users} />
        </div>
      </Router>
    )
  }
}

export default App

FAQ

在刚开始使用 react-router 时, 可能会有些疑问, 我整理了自己在使用中一些疑惑:

match 是如何注入到 Component 中的

match, location, history 这 3 个 object, 是由 Route Component 作为 props 注入到它的 render 方法, 或者 component={xxx} prop 对应的组件中的

match.path 和 match.url 有什么区别

  • match.path 是用来做匹配用的, 也就是在 Route 中使用的
  • match.url 是用来迁移页面用的, 也就是在 Link 中使用的

比如上面的例子中, 对于 /users

  • match.path 是 users:name/:age
  • match.url 是 /users/test/16

BrowserRouter 和 HashRouter 有什么区别

  • BrowserRouter 是用于和 Server 有交互的 Router
  • HashRouter 是用于静态文件服务的 Router

Route 和 Switch 的区别

当有多个 Route 并列时, 如果外层没有包裹 Switch, 那么匹配到的 Route 都会被 render, 如果有 Switch, 那么只会 render 第一个匹配上的 Route

Route 如果不设置 path, 则每次都会匹配成功

NavLink 是一种特殊的 Link, 它可以设置一些 active 时的样式.

路由信息和 redux 状态管理如何结合

路由信息本质上也是一种状态信息, 放不放在 redux 中来管理, 相信很多人都会纠结. 官方的建议是不要把路由的状态放在 redux 的 store 中来管理, 理由如下:

  1. 路由状态一般只有 Components 才关心, 不管放不放在 redux 中, Component 的代码不会有什么改变
  2. 大部分情况下, 路由跳转都是通过 Link, NavLink, Redirct 来完成, 如果需要通过代码, 或者异步 action 中来跳转, 可以通过传入 history 对象来完成.
  3. 路由变化一般不需要通过时间旅行(time travel, redux 的一个调试工具)来 debug.
posted @ 2019-02-01 14:00  wang_yb  阅读(572)  评论(0编辑  收藏  举报