React学习之React-Router V4实战

React Router 4是一组导航组件,在你的React应用程序中提供声明性路由。在这个教程中,将通过一个实际的例子来介绍React Router 4是怎样使用的。

在几乎每个应用程序的体系结构中,路由都是极其重要的。应用程序越大,路由功能就越复杂,从简单到深度嵌套的路由场景。

在React构建的应用程序中,React Router 是最受欢迎使用最普遍的路由库,随着你的应用程序不断变大变复杂,那就需要多个视图和路由,选择一个好的路由库来帮助管理视图之间的转换、重定向、获取URL参数等,让这些操作变得更加的简单,方便。

在此之前,之前版本的React Router涉及预先声明应用程序的路由,在呈现之前声明文件中的所有路径作为应用程序初始化的一部分。使用React Router 4,你可以以声明方式进行路由。 React Router 4的API基本上都是组件,因此如果你已经在React中组合了组件,它就很容易使用。让我们开始吧!

设置和安装

你需要:

  • Node.js (6.0版本或更高版本) 和 npm.
  • create-react-app用于引导新项目。

React Router有这几个包组成:react-routerreact-router-domreact-router-native

  • react-router: 包括核心路由组件。
  • react-router-dom:包含浏览器所需的路由API。
  • react-router-native:包含移动端应用所需的路由API。

使用create_react_app创建一个新项目,然后导航到如下所示创建的目录。

create-react-app bose
cd bose

安装 react-router-dom

npm install --save react-router-dom

我们将覆盖哪些内容?

我们将专注于在浏览器端使用React Router 4。我们将介绍下面列出的非常重要的概念:

  • 基本路由
  • 嵌套路由和url参数
  • 路由保护和认证
  • 自定义Link组件
  • 处理不存在的路由
  • 渲染SideBar

基本路由(Basic Routing)

在React应用中有两种路由组件可用,BrowserRouterHashRouter,前者组成的url不带#,而后者则带有。

注意:如果要构建支持旧版浏览器的Web应用程序,建议使用HashRouter。

打开src/index.js文件,并添加以下代码:

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(
  
    
  , document.getElementById('root'));
registerServiceWorker();

在上面代码中,我们从react-router-dom导入了BrowserRouter, Route, 和 Link组件,并通过Router组件(是BrowserRouter的别名)包裹App组件。路由器组件是成功路由的第一步,它充当其他每个路由组件的容器。另外,Router组件只能有唯一一个子元素或子组件。现在,我们该怎样定义路由呢?

打开src/App.js,我们将路由定义在这里。

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


const Home = () => (
  

Home

); const Airport = () => (
  • Jomo Kenyatta
  • Tambo
  • Murtala Mohammed
); const City = () => (
  • San Francisco
  • Istanbul
  • Tokyo
); class App extends Component { render() { return (
  • Home
  • Airports
  • Cities
); } } export default App;

在上面代码中,使用了Link 组件将用户定向到/, /airports, 和/cities。这些链接中的每一个都有一个组件,一旦当前位置与路由的路径匹配,就应该渲染该组件。然而,事实并不是这样的。让我们接着往下看。

React学习之React-Router V4实战_第1张图片

Airports route

作为Home组件的视图Home应仅匹配/时,才在根组件上显示。然后它在所有的路由上都渲染了。路径/匹配/airports/cities路由。因此会在其他两个路由中渲染Home组件,那么比较简单的解决方法是在/的路由组件上添加exact

src/App.js




React学习之React-Router V4实战_第2张图片

  • Airports路由现在就没有渲染Home UI组件了*。

在上面的例子中,所有的组件有一个component属性,作用是当访问的URL匹配所配置的路由的路径时,渲染一个组件。如果你只想渲染一个小函数而不是整个组件,该怎么办?正如下面的代码一样,你可以使用render属性来展示。

 (
This is the airport route
)}/>

嵌套路由和URL参数

如果你希望URL像/courses/business,/courses/technology/,你会怎么去实现它?

src/App.js

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


const Courses = ({ match }) => (
  
  • Technology
  • Business
  • Economics
(
This is technology
)}/> (
This is business
)}/> (
This is economics
)}/>
); /* Home Component */ // code hidden /* City Component */ //code hidden class App extends Component { render() { return (
  • Home
  • Courses
  • Cities
); } } export default App;

如果当前的URL匹配路径/courses,然后通过Courses组件渲染了technology、business、economics链接,更进一步来说,如果当前的URL匹配/courses/technology/courses/business/courses/economics等的路径,This is technology, This is businessThis is economics就能够渲染呈现在页面上。

作为一名开发人员,我相信你已经用一双重构眼睛看着这种方法了。在上面比较简单的代码中,有很多重复和硬编码。代码行越多,改变理由就越难。让我们来重构一下。

React Router 4附带了一个匹配API,当一个路由的路径成功与当前的URL匹配时创建这个匹配对象。这个匹配对象有一些属性,但是我将列出你应该马上知道的一些属性:

  • match.url: 返回一个显示URL的字符串
  • match.path:返回一个显示路由的路径字符串
  • match.params:返回一个具有从URL解析的值的对象

让我们一步一步的重构,就像这样使用匹配对象来重构Courses组件:

const Courses = ({ match }) => (
  
  • Technology
  • Business
  • Economics
(
This is technology
)}/> (
This is business
)}/> (
This is economics
)}/>
);

测试一下如果你的URL是正常运行的,使用match.path来对Route组件做同样的事。

const Courses = ({ match }) => (
  
  • Technology
  • Business
  • Economics
(
This is technology
)}/> (
This is business
)}/> (
This is economics
)}/>
);

检查你的应用,应该是处于较好的运行状态的。现在最后一步,我们可以使用一行代码来替换上面的三行代码。

const Courses = ({ match }) => (
  
  • Technology
  • Business
  • Economics
(
This is {match.params.course}
)}/>
);

我们使用了match.params,它针对URL的位置提供了一个键值对的对象。:course是URL的参数。因此match.params.course针对正确的URL提供了一个值。

保护路由和认证

当开发一个web应用时,在某些情况下,必须保护某些路由不被访问。在大多数情况下,这些路由只能被授权用户所访问。

在之前的React Router版本,如v3。保护路由的代码像下面这样:

index.js

const Root = () => {
  return (
    
) }

组件有一个onEnter属性,它接受一种允许根据用户的身份验证状态输入或拒绝URL位置的方法。现在,它与React Router 4不同。

让我们来创建三个组件,分别是Public, Private, Login

App.js

import React, { Component } from 'react';
import {
  Route,
  Link,
  BrowserRouter as Router,
} from 'react-router-dom';

const Public = () => (
  
This is a public page
); const Private = () => (
This is a private page
); const Login = () => (
Login Page
); class App extends Component { render() { return (
  • Public
  • Private

); } } export default App;

React学习之React-Router V4实战_第3张图片
现在我们能够访问/public, /private这两个路由。现在,让我们来确保/private路由不能被访问,知道用户已经登录了。React Router 4使用了一个声明式的方法,所以我们能够方便地使用一个如的组件,然而react router 4并没有提供它,我们来构建它。我们想到了一个授权服务。

在这个例子中,授权服务(Auth Service)是一个如下简单的对象:

const AuthService = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true
    setTimeout(cb, 100)
  },
  logout(cb) {
    this.isAuthenticated = false
    setTimeout(cb, 100)
  }
}

现在,我们来构建

const SecretRoute = ({ component: Component, ...rest }) => (
   (
    AuthService.isAuthenticated === true
      ? 
      : 
  )} />
);

上面的代码简单地说明了,当授权状态对于用户是true,组件将渲染,否则用户可能被重定向到/login路由,让我们来试一下。

App.js

import React, { Component } from 'react';
import {
  Route,
  Link,
  Redirect,
  BrowserRouter as Router,
} from 'react-router-dom';

const Login = () => (
  
Login Page
); const AuthService = { isAuthenticated: false, authenticate(cb) { this.isAuthenticated = true setTimeout(cb, 100) }, logout(cb) { this.isAuthenticated = false setTimeout(cb, 100) } }; const SecretRoute = ({ component: Component, ...rest }) => ( ( AuthService.isAuthenticated === true ? : )} /> ); class App extends Component { render() { return (
  • Public
  • Private

); } } export default App;

React学习之React-Router V4实战_第4张图片
当链接Private链接时,被迫重定向到了/login路由。很好,让我们更进一步通过尝试实际的登录和注销流程。像下面这样修改login组件:

App.js

...
class Login extends React.Component {
  state = {
    redirectToPreviousRoute: false
  };

  login = () => {
    AuthService.authenticate(() => {
      this.setState({ redirectToPreviousRoute: true });
    });
  };

  render() {
    const { from } = this.props.location.state || { from: { pathname: "/" } };
    const { redirectToPreviousRoute } = this.state;

    if (redirectToPreviousRoute) {
      return ;
    }

    return (
      

You must log in to view the page at {from.pathname}

); } }

我们修改了登录组件,增加了一个login方法并且当用户拒绝访问的时候重定向到用户想要登录进入的组件,这对于你的路由系统来说是一种典型的行为,并且当用户访问的时候,会重定向到另一个页面。

现在我们在中我们不得不修改组件中的属性:

const SecretRoute = ({ component: Component, ...rest }) => (
   (
    AuthService.isAuthenticated === true
      ? 
      : 
  )} />
);

到这里差不多完成了。然而,当用户成功登陆获取授权后提供一个退出登录按钮是不是更好呢?让我们创建一个组件。

App.js

...
const AuthStatus = withRouter(({ history }) => (
  AuthService.isAuthenticated ? (
    

Welcome!

) : (

You are not logged in.

) ));

在上面简单的示例代码中,我们使用了withRouterhistory.push。其中withRouter是一个来自React Router 的高阶组件,当拥有相同属性的路由改变的时候它能够重新渲染组件。history.push是使用React Router中的组件重定的一种方法。

现在,继续渲染组件

App.js

class App extends Component {
  render() {
    return (
      
        
  • Public
  • Private

); } }

现在,重新在浏览器中试一下,你应该能够成功地登录和退出登录。

自定义Link组件

怎样自定义Link组件?其实很简单。你将学习如何自定义链接,以便在特定链接处于激活状态时具有独特外观,React Router 4有一种很容易实现这个任务的方法。

你的App.js代码如下:

import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'


const Home = () => (
  

Home Page

) const Contact = () => (

Contact Page

) class App extends React.Component { render() { return (
Home Contact
) } } export default App;

负责使管理不同的处于激活状态的链接。

const CustomLink = ({ children, to, exact }) => (
   (
    
{match ? '> ' : ''} {children}
)}/> );

这并不复杂,能够驱动。在上面的代码中,当路由路径匹配URL位置时,使用了match对象来决定是否添加>标志。

这里有三种渲染组件的方式:, 。上面的代码使用了children属性,此渲染属性接受一个函数,该函数接收与组件和渲染函数相同的所有路径属性,除非路径与URL位置不匹配。此过程使你能够根据路由是否匹配来动态调整UI。并且也是我们需要的来创建一个自定义Link组件的方式。

处理不存在的路由

作为一个开发者,你需要处理某个路由不存在的场景。如果一个用户访问了你的网站,并且访问了一个不存在的路由,如/babalawo,你会做什么?难道你就这样准许你的网站挂了?接下来一起来处理这样的场景。

App.js

import React, { Component } from 'react';
import {
  Route,
  Link,
  Redirect,
  Switch,
  BrowserRouter as Router,
} from 'react-router-dom';

const Home = () => (
  

Home Page

) const Contact = () => (

Contact Page

) class App extends Component { render() { return (
  • Home
  • Contact
(
Sorry, this page does not exist.
)} />
); } } export default App;

在上面的代码中,我们引入了一个来自React Router新的组件,并将我们的组件包裹在组件中。现在,如果访问的URL链接已所定义的带有路径的路由不匹配的话, 组件引用了一个没有配置路径,且只有一个render方法的

在你的浏览器中试着访问一个不存在的URL,网页上将显示一条Sorry, this page does not exist的信息。

React学习之React-Router V4实战_第5张图片

渲染侧边栏

长时间里,侧边栏一直存在于app中,让我们学习使用React Router 4怎样创建一个侧边栏。第一步就是将我们的路由放在一个数组中:

import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link,
} from 'react-router-dom'

const routes = [
  { path: '/',
    exact: true,
    leftbar: () => 
Home
, main: () =>

Home

}, { path: '/about', leftbar: () =>
About
, main: () =>

About

}, { path: '/contact', leftbar: () =>
Contact
, main: () =>

Contact

} ] class App extends React.Component { render() { return (
  • Home
  • About
  • Contact
) } } export default App

在上面的代码中,我们定义了一个leftbarmain的键,他们很快就会派上用场,让我们的工作变得非常轻松。

现在我们要做的就是遍历这个数组:

App.js

render() {
  return (
    
      
  • Home
  • About
  • Contact
{routes.map((route) => ( ))}
{routes.map((route) => ( ))}
) }

React学习之React-Router V4实战_第6张图片
上面的代码中,无论路由的路径如何匹配URL的位置,左边栏的组件都会重新渲染。

你可能感兴趣的:(auth,react-router4,react.js)