React Router v4入门学习记录: 单页应用的路由实践

React Router V4(俗称 第四代react-router)相对V2/V3几乎完全重写了,遵循 Just Component 的 API 设计理念。

本篇文章中,我们会构建一个简单的单页应用,来理解React Router的基本使用,内容:

  • 选择哪种路由: HashRouter、BrowserRouter
  • Route的核心内容: path、exact、component、render等
  • 使用Link实现路由跳转

一、如何构建单页应用?

假如你还不会构建一个简单的单页应用,请参考笔者之前的React入门文章 - react入门教程01 - 简介、开发环境搭建、创建第一个React应用

二、完整代码实现

codesandbox

三、安装

React Router V4被分成了三个包: react-routerreact-router-domreact-router-native

其中第一个react-router是不能被直接安装的。该包提供了路由的核心组件和方法。另外两个包分别提供了两个环境的路由: 浏览器原生

这里,我们构建单页网页,只需要安装react-router-dom

// npm
npm install --save react-router-dom

// yarn 
yarn add react-router-dom

四、核心概念

4.1 Router

开始具体的代码实现之前,我们需要决定使用哪一类型路由。在浏览器运行环境中,有两种路由组件,BrowserRouterHashRouter组件。在下面的单页应用中,我们使用BrowserRouter

4.2 History

每个路由对象会创建一个历史history对象, 创建 browser history, 创建 hash history。若你想深入理解history,参考这篇文章。

4.3 Routes

在V3中,不是一个真正的组件,而是作为一个标签用来创建route配置对象。

使用 v4,您可以像常规的 React 程序一样布局您应用中的组件,您要根据位置(特别是其 pathname )呈现内容的任何位置,您将呈现

在 v4, 其实是一个组件,所以无论你在哪里渲染 ,它里面的内容都会被渲染。当 的 path 与当前的路径匹配时,它将会渲染 component, render, orchildren 属性中的内容,当 的 path 与当前的路径不匹配时,将会渲染 null

4.4 Path

Router需要一个path字符串属性,描述路由的路径地址。比如,会匹配以/roster为前缀的路径地址。当匹配到当前的路径时,路由会渲染一个React元素;不匹配的话,就不会渲染。


// when the pathname is '/', the path does not match
// when the pathname is '/roster' or '/roster/2', the path matches
// If you only want to match '/roster', then you need to use
// the "exact" prop. The following will match '/roster', but not
// '/roster/2'.

// You might find yourself adding the exact prop to most routes.
// In the future (i.e. v5), the exact prop will likely be true by
// default. For more information on that, you can check out this 
// GitHub issue:
// https://github.com/ReactTraining/react-router/issues/4958

4.5 match

当路由的path匹配时,会创建一个match对象,该对象的属性如下:

  • url - 当前的路径
  • path - path属性值
  • isExact - path == pathname
  • params - 通过path-to-regexp从路径中抓取的数据

你可以通过[route tester](https://pshrmn.github.io/route-tester/#/)网站来玩转路由match实现

更多路径匹配,请看这里。�

4.6 Switch

在v3中,您可以指定一些子路由,并且只会渲染匹配到的第一个。

v4 通过 组件提供了相似的功能,当 被渲染时,它仅会渲染与当前路径匹配的第一个子

4.6 Redirect

如果你想从一个路径重定向到另一个,在V4,你可以使用达到效果。

// v4
 } />


  
  
  

4.7 Link

跳转用的标签。

五、编码部分

接下来,开始实现编码部分。

5.1

首先,我们先定义一个 组件。为简化实现,我们将应用分成两部分:

。Heander组件包含应用的导航链接;Main组件负责内容的渲染。

import React from 'react'
import Header from './Header'
import Main from './Main'

const App = () => (
  
); export default App

5.2 创建路由

下面,我们定义该单页应用的路径地址:

  • / - 首页
  • /roster - 团队执勤名单
  • /roster/:number - 团队成员的个人页
  • /schedule - 执勤安排表
    
      
      
      
    

Route有三个属性可以用来渲染组件,每个只能有其中一个属性值。

  • component - 它的值是一个组件,在path匹配成功之后会绘制这个组件;
  • render - 一个返回React组件的方法,跟component的效果差不多,但可以传入“render prop”;
  • children - 返回一个React组件的方法,这个总是会绘制,即使没有匹配的路径的时候。


const extraProps = { color: 'red' }
 (
  
)}/>

 (
  props.match
    ? 
    : 
)}/>

通常,component属性和render属性会经常被使用,而children属性不太常用。我们暂时不需要传入额外的参数给渲染组件,所以这里的使用component属性。

上述定义了该应用的基础路由结构,接下来 给出完成的Main组件实现:

import React from 'react'
import { Switch, Route } from 'react-router-dom'
import Home from './Home'
import Roster from './Roster'
import Schedule from './Schedule'

const Main = () => (
  
) export default Main

5.3 嵌套路由

团队成员的个人页/roster/:number并未在上述的实现中定义。实际上,这个路由会被这个以/roster为前缀的组件渲染。

Roster组件中,我们需要渲染两部分内容:

  • /roster - 完整的团队执勤名单页,使用exact完全匹�配
  • /roster/:number - 团队成员的个人页,路由通过抓取/roster后面的地址名字来获取参数
const Roaster = () => (
  
    
    
  
)

这种方式可以很好地将相同前缀的一组路由 统一放入一个组件中实现,更好的管理、归类。

下面是完整的实现:

import React from 'react'
import { Switch, Route } from 'react-router-dom'
import FullRoster from './FullRoster'
import Player from './Player'

const Roster = () => (
  

This is a roster page!

) export default Roster

5.4 路由参数

有时候我们需要抓取路径地址中的参数,例如,团队成员的个人页需要抓取员工的工号。

/roster/:number中的:number就是需要抓取的员工工号,被储存在match.params.number。例如,/roster/6params数据是: { number: '6' } // note that the captured value is a string

组件可以使用props.match.params数据来渲染相应员工的数据。

const Player = props => {
  const player = PlayerApi.get(
    parseInt(props.match.params.number, 10)
  );
  if (!player) {
    return (
Sorry, but the player was not found.
) } return (

{player.name} (#{player.number})

Position: {player.position}

Back
); };

5.5

其他组件的实现:

// Schedule.js
import React from "react";

const Schedule = () => (
  
  • 6/5 @ Evergreens
  • 6/8 vs Kickers
  • 6/14 @ United
); export default Schedule; // FullRoster.js import React from "react"; import { Link } from "react-router-dom"; import PlayerAPI from "../api"; const FullRoaster = () => (
    {PlayerAPI.all().map(p => (
  • {p.name}
  • ))}
); export default FullRoaster;

六、最后

我们最后实现

组件使用元素将所有页面串联起来,当你点击时,URL更新的同时,仅重新渲染相应的组件,并不需要全部重新渲染。

import React from "react";
import { Link } from "react-router-dom";

// The Header creates links that can be used to navigate
// between routes.
const Header = () => (
  
); export default Header;

七、参考

  • A Simple React Router v4 Tutorial
  • REACT TRAINING / REACT ROUTER

你可能感兴趣的:(React Router v4入门学习记录: 单页应用的路由实践)