【React新手学习指南】06 小白也能看懂的React Router教程

写在前面,大家好!我是【跨考菌】,一枚跨界的程序猿,专注于后台技术的输出,目标成为全栈攻城狮!这博客是对我跨界过程的总结和思考。如果你也对Java后端技术感兴趣,抑或是正在纠结于跨界,都可以关注我的动态,让我们一起学习,一起进步~
我的博客地址为:【跨考菌】的博客

目录

  • 1 react router理解
    • 1.1 react router概述
    • 1.2 SPA理解
    • 1.3 路由的理解
    • 1.4 前端路由的实现
  • 2 react-router API
    • 2.1 组件
    • 2.2 其他
  • 3 基本路由使用
    • 3.1 效果
    • 3.2 准备
    • 3.3 路由组件: views/about.jsx
    • 3.4 路由组件: views/home.jsx
    • 3.5 包装NavLink组件: components/my-nav-link.jsx
    • 3.6 应用组件: components/app.jsx
    • 3.7 入口JS: index.js
  • 4 嵌套路由使用
    • 4.1 效果
    • 4.2 二级路由组件: views/news.jsx
    • 4.3 二级路由组件: views/message.jsx
    • 4.4 一级路由组件: views/home.jsx
  • 5 向路由组件传递参数数据
    • 5.1 效果
    • 5.2 三级路由组件: views/message-detail.jsx
    • 5.3 二级路由组件: views/message.jsx
  • 6 多种路由跳转方式
    • 6.1 效果
    • 6.2 二级路由: views/message.jsx


上篇【React新手学习指南】05 React组件通讯|监听原理总结 对React核心知识点做下总结。本文开始介绍React router的相关内容。和【跨考菌】一起加油吧~

在这里插入图片描述

如果你觉得对你有帮助的话,记得帮博主一键三连哦


1 react router理解

1.1 react router概述

1) react的一个插件库
2)专门用来实现一个SPA应用
3)基于react的项目基本都会用到此库

1.2 SPA理解

1)单页Web应用(single page web application,SPA)
2) 整个应用只有一个完整的页面
3) 点击页面中的链接不会刷新页面, 本身也不会向服务器发请求
4) 当点击路由链接时, 只会做页面的局部更新
5) 数据都需要通过ajax请求获取, 并在前端异步展现

1.3 路由的理解

1) 什么是路由?
a. 一个路由就是一个映射关系(key:value)
b. key为路由路径, value可能是function/component

2) 路由分类
a. 后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据
b. 前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件

3) 后台路由
a. 注册路由: router.get(path, function(req, res))
b. 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据

4) 前端路由
a. 注册路由:
b. 当浏览器的hash变为#about时, 当前路由组件就会变为About组件

1.4 前端路由的实现

1) history库
a. 网址: https://github.com/ReactTraining/history
b. 管理浏览器会话历史(history)的工具库
c. 包装的是原生BOM中window.history和window.location.hash

2) history API
a. History.createBrowserHistory(): 得到封装window.history的管理对象
b. History.createHashHistory(): 得到封装window.location.hash的管理对象
c. history.push(): 添加一个新的历史记录
d. history.replace(): 用一个新的历史记录替换当前的记录
e. history.goBack(): 回退到上一个历史记录
f. history.goForword(): 前进到下一个历史记录
g. history.listen(function(location){}): 监视历史记录的变化

3) 测试

【React新手学习指南】06 小白也能看懂的React Router教程_第1张图片

【React新手学习指南】06 小白也能看懂的React Router教程_第2张图片

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>history test</title>
</head>
<body>
  <p><input type="text"></p>
  <a href="/test1" onclick="return push('/test1')">test1</a><br><br>
  <button onClick="push('/test2')">push test2</button><br><br>
  <button onClick="back()">回退</button><br><br>
  <button onClick="forword()">前进</button><br><br>
  <button onClick="replace('/test3')">replace test3</button><br><br>

  <script type="text/javascript" src="https://cdn.bootcss.com/history/4.7.2/history.js"></script>
  <script type="text/javascript">
    let history = History.createBrowserHistory() // 方式一
    // history = History.createHashHistory() // 方式二
    // console.log(history)

    function push (to) {
      history.push(to)
      return false
    }

    function back() {
      history.goBack()
    }

    function forword() {
      history.goForward()
    }

    function replace (to) {
      history.replace(to)
    }

    history.listen((location) => {
      console.log('请求路由路径变化了', location)
    })
  </script>
</body>
</html>

2 react-router API

2.1 组件

  1. :不带#号的
  2. :路由链接
  3. :导航路由链接
  4. :可以包含多个连接

2.2 其他

  1. history对象
  2. match对象
  3. withRouter函数

3 基本路由使用

3.1 效果

【React新手学习指南】06 小白也能看懂的React Router教程_第3张图片

3.2 准备

  1. 下载react-router: npm install --save react-router@4
  2. 引入bootstrap.css:

3.3 路由组件: views/about.jsx

import React from 'react'
export default function About() {
  return <div>About组件内容</div>
}

3.4 路由组件: views/home.jsx

import React from 'react'
export default function Home() {
  return <div>Home组件内容</div>
}

3.5 包装NavLink组件: components/my-nav-link.jsx

import React from 'react'
import {NavLink} from 'react-router-dom'

export default function MyNavLink(props) {
  return <NavLink {...props} activeClassName='activeClass'/>
}

3.6 应用组件: components/app.jsx

import React from 'react'
import {Route, Switch, Redirect} from 'react-router-dom'
import MyNavLink from './my-nav-link'
import About from '../views/about'
import Home from '../views/home'

export default class App extends React.Component {

  render() {
    return (
      <div>
        <div className="row">
          <div className="col-xs-offset-2 col-xs-8">
            <div className="page-header">
              <h2>React Router Demo</h2>
            </div>
          </div>
        </div>

        <div className="row">
          <div className="col-xs-2 col-xs-offset-2">
            <div className="list-group">
              {/*导航路由链接*/}
              <MyNavLink className="list-group-item" to='/about'>About</MyNavLink>
              <MyNavLink className="list-group-item" to='/home'>Home</MyNavLink>
            </div>
          </div>
          <div className="col-xs-6">
            <div className="panel">
              <div className="panel-body">
                {/*可切换的路由组件*/}
                <Switch>
                  <Route path='/about' component={About}/>
                  <Route path='/home' component={Home}/>
                  <Redirect to='/about'/> // 默认重定向到哪个地址!!
                </Switch>
              </div>
            </div>
          </div>
        </div>
      </div>
    )
  }
}

3.7 入口JS: index.js

import React from 'react'
import ReactDOM from 'react-dom'
import {BrowserRouter, HashRouter} from 'react-router-dom'
import App from './components/app'

import './index.css'

ReactDOM.render(
  (
    <BrowserRouter>
      <App/>
    </BrowserRouter>
    /*
      
    */
  ),

  document.getElementById('root')
)

4 嵌套路由使用

4.1 效果

【React新手学习指南】06 小白也能看懂的React Router教程_第4张图片

4.2 二级路由组件: views/news.jsx

import React from 'react'

export default class News extends React.Component {
  state = {
    newsArr: ['news001', 'news002', 'news003']
  }

  render () {
    return (
      <div>
        <ul>
          {
            this.state.newsArr.map((news, index) => <li key={index}>{news}</li>)
          }
        </ul>
      </div>
    )
  }
}

4.3 二级路由组件: views/message.jsx

import React from 'react'
import {Link, Route} from 'react-router-dom'
import MessageDetail from "./message-detail"

export default class Message extends React.Component {
  state = {
    messages: []
  }

  componentDidMount () {
    // 模拟发送ajax请求
    setTimeout(() => {
      const data = [
        {id: 1, title: 'Message001'},
        {id: 3, title: 'Message003'},
        {id: 6, title: 'Message006'},
      ]
      this.setState({
        messages: data
      })
    }, 1000)
  }

  ShowDetail = (id) => {
    this.props.history.push(`/home/message/${id}`)
  }

  ShowDetail2 = (id) => {
    this.props.history.replace(`/home/message/${id}`)
  }

  back = () => {
    this.props.history.goBack()
  }

  forward = () => {
    this.props.history.goForward()
  }

  render () {
    const path = this.props.match.path

    return (
      <div>
        <ul>
          {
            this.state.messages.map((m, index) => {
              return (
                <li key={index}>
                  <Link to='???'>{m.title}</Link>
                </li>
              )
            })
          }
        </ul>
        <p>
          <button onClick={this.back}>返回</button>&nbsp;
          <button onClick={this.forward}>前进</button>&nbsp;
        </p>
        <hr/>
        <Route path={`${path}/:id`} component={MessageDetail}></Route>
      </div>
    )
  }
}

4.4 一级路由组件: views/home.jsx

import React from 'react'
import {Switch, Route, Redirect} from 'react-router-dom'
import MyNavLink from '../components/my-nav-link'
import News from './news'
import Message from './message'

export default function Home() {
  return (
    <div>
      <h2>Home组件内容</h2>
      <div>
        <ul className="nav nav-tabs">
          <li>
            <MyNavLink to='/home/news'>News</MyNavLink>
          </li>
          <li>
            <MyNavLink to="/home/message">Message</MyNavLink>
          </li>
        </ul>
        <Switch>
          <Route path='/home/news' component={News} />
          <Route path='/home/message' component={Message} />
          <Redirect to='/home/news'/>
        </Switch>
      </div>
    </div>
  )
}

5 向路由组件传递参数数据

5.1 效果

【React新手学习指南】06 小白也能看懂的React Router教程_第5张图片

5.2 三级路由组件: views/message-detail.jsx

import React from 'react'

const messageDetails = [
    {id: 1, title: 'Message001', content: '我爱你, 中国'},
    {id: 3, title: 'Message003', content: '我爱你, 老婆'},
    {id: 6, title: 'Message006', content: '我爱你, 孩子'},
]

export default function MessageDetail(props) {

    const id = props.match.params.id
    console.log('id: ', id)

    const md = messageDetails.find(md => md.id === id * 1)

    return (
        <ul>
            <li>ID: {md.id}</li>
            <li>TITLE: {md.title}</li>
            <li>CONTENT: {md.content}</li>
        </ul>
    )
}

5.3 二级路由组件: views/message.jsx

import React from 'react'
import {Link, Route} from 'react-router-dom'
import MessageDetail from "./views/message-detail"

export default class Message extends React.Component {
  state = {
    messages: []
  }

  componentDidMount () {
    // 模拟发送ajax请求
    setTimeout(() => {
      const data = [
        {id: 1, title: 'Message001'},
        {id: 3, title: 'Message003'},
        {id: 6, title: 'Message006'},
      ]
      this.setState({
        messages: data
      })
    }, 1000)
  }

  render () {
    const path = this.props.match.path

    return (
      <div>
        <ul>
          {
            this.state.messages.map((m, index) => {
              return (
                <li key={index}>
                  <Link to={`${path}/${m.id}`}>{m.title}</Link>
                </li>
              )
            })
          }
        </ul>
        <hr/>
        <Route path={`${path}/:id`} component={MessageDetail}></Route>
      </div>
    )
  }
}

6 多种路由跳转方式

6.1 效果

【React新手学习指南】06 小白也能看懂的React Router教程_第6张图片

6.2 二级路由: views/message.jsx

import React from 'react'
import {Link, Route} from 'react-router-dom'
import MessageDetail from "./views/message-detail"

export default class Message extends React.Component {
  state = {
    messages: []
  }

  componentDidMount () {
    // 模拟发送ajax请求
    setTimeout(() => {
      const data = [
        {id: 1, title: 'Message001'},
        {id: 3, title: 'Message003'},
        {id: 6, title: 'Message006'},
      ]
      this.setState({
        messages: data
      })
    }, 1000)
  }

  ShowDetail = (id) => {
    this.props.history.push(`/home/message/${id}`)
  }

  ShowDetail2 = (id) => {
    this.props.history.replace(`/home/message/${id}`)
  }

  back = () => {
    this.props.history.goBack()
  }

  forward = () => {
    this.props.history.goForward()
  }

  render () {
    const path = this.props.match.path

    return (
      <div>
        <ul>
          {
            this.state.messages.map((m, index) => {
              return (
                <li key={index}>
                  <Link to={`${path}/${m.id}`}>{m.title}</Link>
                  &nbsp;
                  <button onClick={() => this.ShowDetail(m.id)}>查看详情(push)</button>&nbsp;
                  <button onClick={() => this.ShowDetail2(m.id)}>查看详情(replace)</button>
                </li>
              )
            })
          }
        </ul>
        <p>
          <button onClick={this.back}>返回</button>&nbsp;
          <button onClick={this.forward}>前进</button>&nbsp;
        </p>
        <hr/>
        <Route path={`${path}/:id`} component={MessageDetail}></Route>
      </div>
    )
  }
}

在这里插入图片描述
如果对你有帮助,记得帮博主一键三连哦

你可能感兴趣的:(React新手学习指南,js,react)