react-router v4 学习实践

最近学习了 react-router v4,根据官方 API 文档和网上资源做了一个简单的路由示例。

先用官方的工具 create-react-app  初始化一个 react 项目模板,再根据自己的需要修改。

要实现的路由:

1. 登录页(/login)

2. 主页(/home):一级导航

3. 商品管理(/goods):一级导航

4. 商品列表(/goods/list):二级导航

5. 商品品牌(/goods/brand):二级导航

6. 路由重定向:

(1)未登录时,地址栏输入主域名(localhost:3000),页面重定向到登录页;否则,重定向到主页。

(2)点击一级导航“商品管理”时,重定向到其下的第一个子导航“商品列表”。

(3)退出后,重定向到登录页。

项目结构:

├── app
│   ├── public
│   │   ├── favicon.ico
│   │   ├── index.html
│   │   └── manifest.json
│   ├── src
│   │   ├── assets
│   │   │   ├── app.css
│   │   │   └── logo.svg
│   │   ├── common
│   │   │   └── RouteWithSubRoutes.js
│   │   ├── modules
│   │   │   ├── asideContainer
│   │   │   │   └── Goods.js
│   │   │   ├── container
│   │   │   │   ├── Container.js
│   │   │   │   ├── Header.js
│   │   │   │   └── Home.js
│   │   │   ├── error
│   │   │   │   └── NotFound.js
│   │   │   ├── goods
│   │   │   │   ├── Brand.js
│   │   │   │   └── List.js
│   │   │   ├── login
│   │   │   │   └── Login.js
│   │   ├── index.js
│   │   ├── Routes.js
│   ├── .gitignore
│   ├── package-lock.json
│   ├── package.json
│   └── README.md

路由配置(src/Routes.js):

import React from ‘react‘
import {
  BrowserRouter as Router,
  Switch,
  Route
} from ‘react-router-dom‘

import RouteWithSubRoutes from ‘./common/RouteWithSubRoutes.js‘
import NotFound from ‘./modules/error/NotFound.js‘
import Login from ‘./modules/login/Login.js‘
import Container from ‘./modules/container/Container.js‘
import Home from ‘./modules/container/Home.js‘
import Goods from ‘./modules/asideContainer/Goods.js‘
import List from ‘./modules/goods/List.js‘
import Brand from ‘./modules/goods/Brand.js‘

const routes = [
  { path: ‘/home‘,
    component: Home
  },
  { path: ‘/goods‘,
    component: Goods,
    children: [
      { path: ‘/goods/list‘,
        component: List
      },
      { path: ‘/goods/brand‘,
        component: Brand
      }
    ]
  }
]

export default () => (
  <Router>
    <Switch>
      <Route path=‘/login‘ component={Login} />
      <Container>
        <Switch>
          {routes.map((route, i) => (
            <RouteWithSubRoutes key={i} {...route} />
          ))}
          <Route component={NotFound} />
        </Switch>
      </Container>
    </Switch>
  </Router>
)

重定向需要用到 Redirect 组件,但是我的经验就是,Redirect 不要与 Route 作为同级兄弟一起使用,否则页面会保持在 Redirect 指定的路由,而不能跳到其它的路由:

this.props.history.push 指定的路由就会无效。

RouteWithSubRoutes 参考的是官方的的示例。它是一个函数,接收一个对象作为参数,并返回一个(子)路由。在这里它用于渲染一级导航。

登录(src/modules/login/Login.js):

 1 import React, { Component } from ‘react‘
 2
 3 export default class Login extends Component {
 4   constructor(props) {
 5     super(props)
 6     this.state = {
 7       loggedIn: localStorage.getItem(‘loggedIn‘),
 8       username: ‘anonymous‘,
 9       password: ‘123‘
10     }
11
12     this.onInputChange = this.onInputChange.bind(this)
13     this.onSubmit = this.onSubmit.bind(this);
14   }
15
16   onInputChange(event) {
17     const target = event.target
18     const name = target.name
19     const value = target.value
20
21     this.setState({
22       [name]: value
23     })
24   }
25
26   onSubmit(event) {
27     if (this.state.username && this.state.password) {
28       localStorage.setItem(‘loggedIn‘, true)
29       localStorage.setItem(‘username‘, this.state.username)
30       this.setState({loggedIn: true})
31       this.props.history.push(‘/home‘)
32     }
33   }
34
35   render() {
36     return (
37       <div className=‘login-wrap‘>
38         <h2>登 录</h2>
39         <div className=‘field-box‘>
40           <label className=‘control-label‘>用户名:</label>
41           <input type=‘text‘ name=‘username‘ value={this.state.username} onChange={this.onInputChange} />
42         </div>
43         <div className=‘field-box‘>
44           <label className=‘control-label‘>密  码:</label>
45           <input type=‘password‘ name=‘password‘ value={this.state.password} onChange={this.onInputChange} />
46         </div>
47         <div className=‘field-box‘>
48           <label className=‘control-label‘></label>
49           <button type=‘button‘ onClick={this.onSubmit}>登 录</button>
50         </div>
51       </div>
52     )
53   }
54 }

将用户名写入 localStorage,再通过 this.props.history.push(‘/home‘) 跳转到主页。

Container组件(src/modules/container/Container.js):

 1 import React, { Component } from ‘react‘
 2 import { Redirect } from ‘react-router-dom‘
 3
 4 import Header from ‘./Header‘
 5
 6 class Container extends Component {
 7   constructor() {
 8     super()
 9     this.state = {
10       loggedIn: localStorage.getItem(‘loggedIn‘),
11       test: ‘it is a testing‘
12     }
13   }
14
15   render() {
16     if (!this.state.loggedIn) {
17       return (
18         <Redirect to=‘/login‘ />
19       )
20     } else if (this.props.location.pathname === ‘/‘) {
21       return (
22         <Redirect to=‘/home‘ />
23       )
24     }
25
26     return (
27       <div>
28         <Header {...this.state} />
29         <div className=‘main-layout‘>
30           {this.props.children}
31         </div>
32       </div>
33     )
34   }
35 }
36
37 export default Container

判断用户是否登录,再通过 Redirect 重定向到相应的路由。

this.props.children 用于获取 Container 的子组件。

头部(src/modules/container/Header.js):

 1 import React, { Component } from ‘react‘
 2 import { NavLink, Redirect } from ‘react-router-dom‘
 3
 4 export default class Header extends Component {
 5   constructor(props) {
 6     super(props)
 7     this.state = {
 8       loggedIn: localStorage.getItem(‘loggedIn‘)
 9     }
10   }
11
12   onLogout = () => {
13     localStorage.setItem(‘loggedIn‘, ‘‘)
14     this.setState({loggedIn: false})
15   }
16
17   render() {
18     if (!this.state.loggedIn) {
19       return (
20         <Redirect to=‘/login‘ />
21       )
22     }
23
24     return (
25       <header className=‘fixed-top‘>
26         <div className=‘pull-left‘>
27           <h1>管理平台</h1>
28           <NavLink to=‘/home‘ exact>主页</NavLink>
29           <NavLink to=‘/goods‘>商品管理</NavLink>
30         </div>
31         <div className=‘pull-right‘>
32           <div className=‘header-info‘>
33             欢迎您,{localStorage.getItem(‘username‘)}
34             <span style={{marginLeft: 10}}>|</span>
35             <a className=‘logout‘ onClick={this.onLogout}>退出</a>
36           </div>
37         </div>
38       </header>
39     )
40   }
41 }

退出后,清空 localStorage 中的 loggedIn,并重定向到登录页

<Redirect to=‘/login‘ />

商品管理(src/modules/asideContainer/Goods.js):

import React from ‘react‘
import { NavLink, Route, Redirect } from ‘react-router-dom‘

import RouteWithSubRoutes from ‘../../common/RouteWithSubRoutes.js‘

export default ({ routes, path }) => (
  <div>
    <div className=‘aside-nav‘>
      <NavLink to="/goods/list">商品列表</NavLink>
      <NavLink to="/goods/brand">商品品牌</NavLink>
    </div>

    {
      routes.map((route, i) => {
        return (
          <RouteWithSubRoutes key={i} {...route}/>
        )
      })
    }

    <Route exact path=‘/goods‘ render={() => (
      <Redirect to=‘goods/list‘ />
    )} />
  </div>
)

同样用到了 RouteWithSubRoutes, 在这里它用于渲染二级导航。

通过 Route 判断当前页是“商品管理”(exact 用于路由的严格匹配),再用 Redirect 重定向。

注意,当前路由处于 active 状态,用到的是 NavLink 组件;另一个类似功能的组件是 Link,但没有当前 active 状态。

回过头去看看 Header 组件:

<NavLink to=‘/home‘ exact>主页</NavLink>
<NavLink to=‘/goods‘>商品管理</NavLink>

对于“主页”,添加了 exact 属性,但“商品管理”则没有,为什么?因为当路由跳转到“商品列表”(/goods/list)时,exact 严格匹配 /goods 的结果为 false,模糊匹配的结果才为 true。

时间: 2024-10-13 08:44:18

react-router v4 学习实践的相关文章

[Web 前端] React Router v4 入坑指南

cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子做了升级,之前的路由用的还是v2.7.0版的,所以决定把路由也升级下,正好“尝尝鲜”... 江湖传言,目前官方同时维护 2.x 和 4.x 两个版本.(ヾ(??﹏?)??咦,此刻相信机智如我的你也会发现,ReactRouter v3 去哪儿了?整丢了??巴拉出锅了???敢不敢给我个完美的解释!?)事

[React Router v4] Use the React Router v4 Link Component for Navigation Between Routes

If you’ve created several Routes within your application, you will also want to be able to navigate between them. React Router supplies a Link component that you will use to make this happen. Import Link: import { BrowserRouter as Router, Route, Link

[React Router V4] Create Basic Routes with the React Router v4 BrowserRouter

React Router 4 has several routers built in for different purposes. The primary one you will use for building web applications is the BrowserRouter. In this lesson you will import the BrowserRouter and create some basic Route components. After create

【前端,干货】react and redux教程学习实践(二)。

前言 这篇博文接 [前端]react and redux教程学习实践,浅显易懂的实践学习方法. ,上一篇简略的做了一个redux的初级demo,今天深入的学习了一些新的.有用的,可以在生产项目中使用的前端架构,我将尽量以最简单的语言描述,如果有童鞋看不懂,也可以私下问我. 复习 前一节我们已经知道,一个redux应用,主要有几个概念,它们的共同作用都是管理一个全局state,使react组件的state集中处理,想一下你在写react组件的时候,组件的state总是或多或少与父级组件有关联,一般

React漫漫学习路之 React Router

React Router 是一个基于 React 之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与 URL 间的同步. 目前react-router最新版本已经到4.0+,因为新的版本是一次非常大的改动,所以这里直接讨论4.0以上版本. 引用 react-router // React Router 核心 react-router-dom // 用于 DOM 绑定的 React Router react-router-native // 用于 React Native

关于react router 4 的小实践

详细代码栗子:https://github.com/wayaha/react-dom-CY clone然后 npm install npm start 分割线 1.这个项目使用create-react-app搭建: 首先需要安装好create-react-app npm install -g create-react-app 安装完毕之后就是搭建项目: create-react-app your-project-name cd your-project-name npm start 安装完成之后

Redux+React Router+Node.js全栈开发

详情请交流  QQ  709639943 01.Java深入微服务原理改造房产销售平台 02.跨平台混编框架 MUI 仿豆瓣电影 APP 03.Node.js入门到企业Web开发中的应用 04.Redux+React Router+Node.js全栈开发 05.Java秒杀系统方案优化 高性能高并发实战 06.企业级刚需Nginx入门,全面掌握Nginx配置+快速搭建高可用架构 07.快速上手Linux 玩转典型应用 08.全面系统讲解CSS 工作应用+面试一步搞定 09.Java Spring

react router路由传参

今天,我们要讨论的是react router中Link传值的三种表现形式.分别为通过通配符传参.query传参和state传参. ps:进入正题前,先说明一下,以下的所有内容都是在react-router V4的版本下. 1.通配符传参 Route定义方式: <Route path='/path/:name' component={Path}/> Link组件: <Link to="/path/通过通配符传参">通配符</Link> 参数获取: th

react router 4.0以上的路由应用

thead>tr>th{padding:8px;line-height:1.4285714;border-top:1px solid #ddd}.table>thead>tr>td,.table>tbody>tr>th,.table>tbody>tr>td,.table>tfoot>tr>th,.table>tfoot>tr>td{padding:8px;line-height:1.4285714;ver