React 全栈体系(九)

第五章 React 路由

一、相关理解

1. SPA 的理解

  • 单页 Web 应用(single page web application,SPA)。
  • 整个应用只有一个完整的页面
  • 点击页面中的链接不会刷新 页面,只会做页面的局部更新
  • 数据都需要通过 ajax 请求获取, 并在前端异步展现。

2. 路由的理解

2.1 什么是路由?
  • 一个路由就是一个映射关系(key:value)
  • key 为路径, value 可能是 function 或 component
2.2 路由分类
2.2.1 后端路由
  • 理解: value 是 function, 用来处理客户端提交的请求。
  • 注册路由: router.get(path, function(req, res))
  • 工作过程:当 node 接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据
2.2.2 前端路由
  • 浏览器端路由,value 是 component,用于展示页面内容。
  • 注册路由: <Route path="/test" component={Test}>
  • 工作过程:当浏览器的 path 变为/test 时, 当前路由组件就会变为 Test 组件

3. react-router-dom 的理解

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

二、react-router-dom 相关 API

1. 内置组件

  • <BrowserRouter>
  • <HashRouter>
  • <Route>
  • <Redirect>
  • <Link>
  • <NavLink>
  • <Switch>

2. 其它

  • history 对象
  • match 对象
  • withRouter 函数

三、基本路由使用

1. 效果


2. 准备

2.1 下载 react-router-dom
  • npm install --save react-router-dom
2.2 引入 bootstrap.css:
  • <link rel="stylesheet" href="/css/bootstrap.css">
2.3 注意
  • 由于 react-router-dom 在 2021 年 11 月份升级到了 6 版本,此处是 5 版本的代码展示,需要执行:
bash 复制代码
npm i react-router-dom@5
  • 最新的 6 版本使用会在后续更新

3. 代码 - 路由的基本使用

3.1 index.js
javascript 复制代码
/* src/index.js */
//引入react核心库
import React from "react";
//引入ReactDOM
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
//引入App组件
import App from "./App";

//渲染App到页面
ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);
3.2 App
javascript 复制代码
/* src/App.jsx */
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Home from "./components/Home";
import About from "./components/About";

export default class App extends 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">
              {/* 原生html中,靠<a>跳转不同的页面 */}
              {/* <a className="list-group-item active" href="./about.html">
                About
              </a>
              <a className="list-group-item" href="./home.html">
                Home
              </a> */}
              {/* 在React中靠路由链接实现切换组件 -- 编写路由链接 */}
              <Link className="list-group-item" to="/about">
                About
              </Link>
              <Link className="list-group-item" to="/home">
                Home
              </Link>
            </div>
          </div>
          <div className="col-xs-6">
            <div className="panel">
              <div className="panel-body">
                {/* 注册路由 */}
                <Route path="/about" component={About} />
                <Route path="/home" component={Home} />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}
3.3 Home
javascript 复制代码
/* src/components/Home/index.jsx */
import React, { Component } from 'react'

export default class index extends Component {
  render() {
    return (
        <h3>我是Home的内容</h3>
    )
  }
}
3.4 About
javascript 复制代码
/* src/components/About/index.jsx */
import React, { Component } from 'react'

export default class index extends Component {
  render() {
    return (
      <h3>我是About的内容</h3>
    )
  }
}
3.5 总结
bash 复制代码
1.明确好界面中的导航区、展示区
2.导航区的a标签改为Link标签
	<Link to="/xxxxx">Demo</Link>
3.展示区写Route标签进行路径的匹配
	<Route path='/xxxx' component={Demo}/>
4.<App>的最外侧包裹了一个<BrowserRouter>或<HashRouter>

4. 代码 - 路由组件与一般组件

4.1 App
javascript 复制代码
/* src/App.jsx */
import React, { Component } from "react";
import { Link, Route } from "react-router-dom";
import Home from "./pages/Home";  //Home是路由组件
import About from "./pages/About";  //About是路由组件
import Header from "./components/Header"; //Header是一般组件

export default class App extends Component {
  render() {
    return (
      <div>
        <div className="row">
          <div className="col-xs-offset-2 col-xs-8">
            <Header/>
          </div>
        </div>
        <div className="row">
          <div className="col-xs-2 col-xs-offset-2">
            <div className="list-group">
              <Link className="list-group-item" to="/about">
                About
              </Link>
              <Link className="list-group-item" to="/home">
                Home
              </Link>
            </div>
          </div>
          <div className="col-xs-6">
            <div className="panel">
              <div className="panel-body">
                {/* 注册路由 */}
                <Route path="/about" component={About} />
                <Route path="/home" component={Home} />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}
4.2 Header
javascript 复制代码
/* src/components/Header/index.jsx */
import React, { Component } from "react";

export default class index extends Component {
  render() {
    return (
      <div className="page-header">
        <h2>React Router Demo</h2>
      </div>
    );
  }
}
4.3 About
javascript 复制代码
/* src/pages/About/index.jsx */
import React, { Component } from 'react'

export default class index extends Component {
  render() {
    console.log('About组件收到的props是', this.props);
    return (
      <h3>我是About的内容</h3>
    )
  }
}
4.4 总结
bash 复制代码
1.写法不同:
	一般组件:<Demo/>
	路由组件:<Route path="/demo" component={Demo}/>
2.存放位置不同:
	一般组件:components
	路由组件:pages
3.接收到的props不同:
	一般组件:写组件标签时传递了什么,就能收到什么
	路由组件:接收到三个固定的属性
		history:
					go: ƒ go(n)
					goBack: ƒ goBack()
					goForward: ƒ goForward()
					push: ƒ push(path, state)
					replace: ƒ replace(path, state)
		location:
					pathname: "/about"
					search: ""
					state: undefined
		match:
					params: {}
					path: "/about"
					url: "/about"
5.1 App
javascript 复制代码
/* src/App.jsx */
import React, { Component } from "react";
import { Route } from "react-router-dom";
import Home from "./pages/Home";  //Home是路由组件
import About from "./pages/About";  //About是路由组件
import Header from "./components/Header"; //Header是一般组件

export default class App extends Component {
  render() {
    return (
      <div>
        <div className="row">
          <div className="col-xs-offset-2 col-xs-8">
            <Header/>
          </div>
        </div>
        <div className="row">
          <div className="col-xs-2 col-xs-offset-2">
            <div className="list-group">
              <NavLink activeClassName="alex" className="list-group-item" to="/about">
                About
              </NavLink>
              <NavLink activeClassName="alex" className="list-group-item" to="/home">
                Home
              </NavLink>
            </div>
          </div>
          <div className="col-xs-6">
            <div className="panel">
              <div className="panel-body">
                {/* 注册路由 */}
                <Route path="/about" component={About} />
                <Route path="/home" component={Home} />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}
5.2 index.html
html 复制代码
<!-- public/index.html -->
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<title>React App</title>
		<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
		<link rel="stylesheet" href="/css/bootstrap.css">
		<style>
			.alex{
				background-color: rgb(209, 137, 4) !important;
				color: white !important;
			}
		</style>
	</head>
	<body>
		<div id="root"></div>
	</body>
</html>
6.1 App
javascript 复制代码
/* src/App.jsx */
import React, { Component } from "react";
import { NavLink, Route } from "react-router-dom";
import Home from "./pages/Home";  //Home是路由组件
import About from "./pages/About";  //About是路由组件
import Header from "./components/Header"; //Header是一般组件
import MyNavLink from "./components/MyNavLink";

export default class App extends Component {
  render() {
    return (
      <div>
        <div className="row">
          <div className="col-xs-offset-2 col-xs-8">
            <Header/>
          </div>
        </div>
        <div className="row">
          <div className="col-xs-2 col-xs-offset-2">
            <div className="list-group">
              {/* 在React中靠路由链接实现切换组件 -- 编写路由链接 */}
              <MyNavLink to="/about">About</MyNavLink>
              <MyNavLink to="/home">Home</MyNavLink>
            </div>
          </div>
          <div className="col-xs-6">
            <div className="panel">
              <div className="panel-body">
                {/* 注册路由 */}
                <Route path="/about" component={About} />
                <Route path="/home" component={Home} />
              </div>
            </div>
          </div>
        </div>
      </div>
    );
  }
}
javascript 复制代码
/* src/components/MyNavLink/index.jsx */
import React, { Component } from "react";
import { NavLink } from "react-router-dom";

export default class MyNavLink extends Component {
  render() {
    return (
      <NavLink activeClassName="alex" className="list-group-item" {...this.props}/>
    );
  }
}
6.3 总结
bash 复制代码
1.NavLink可以实现路由链接的高亮,通过activeClassName指定样式名
2.标签体内容是一个特殊的标签属性
3.通过this.props.children可以获取标签体内容
相关推荐
Stringzhua1 小时前
Vue数据的变更操作与表单数据的收集【6】
前端·javascript·vue.js
万少1 小时前
可可图片编辑 HarmonyOS 上架应用分享
前端·harmonyos
你的人类朋友1 小时前
git常见操作整理(持续更新)
前端·git·后端
无羡仙1 小时前
Webpack 核心实战:从零搭建支持热更新与 Babel 转译的现代前端环境
前端·webpack·前端框架
你的人类朋友2 小时前
git中的Fast-Forward是什么?
前端·git·后端
初遇你时动了情2 小时前
uniapp vue3 ts自定义底部 tabbar菜单
前端·javascript·uni-app
JarvanMo2 小时前
天塌了?Flutter工程总监跑去苹果了?
前端
烛阴3 小时前
掌握 TypeScript 的边界:any, unknown, void, never 的正确用法与陷阱
前端·javascript·typescript
Jerry4 小时前
迁移到 Jetpack Compose
前端
FFF-X4 小时前
前端无感刷新 Token 的 Axios 封装方案
前端