Web学习笔记-React(路由)

笔记内容转载自 AcWing 的 Web 应用课讲义,课程链接:AcWing Web 应用课。

CONTENTS

    • 1. Web分类
    • 2. Route组件
    • 3. URL中传递参数
    • 4. Search Params传递参数
    • 5. 重定向
    • 6. 嵌套路由

本节内容是如何将页面和 URL 一一对应起来。

1. Web分类

Web 页面可以分为两大类:

  • 静态页面:页面里的数据是写死的,即整个文件存放在服务器上,当用户访问 URL 时,服务器原封不动地将页面信息传给前端。
  • 动态页面:页面里的数据是动态填充的,即服务器上存的是页面的模板数据是存到数据库里的,当用户打开页面时,会动态将这个页面拼接起来。现在一般都是动态页面。
    • 后端渲染:数据在后端填充,即模板与数据的拼接操作是在服务器端进行的。客户端向服务器端发送 URL,服务器端返回拼接好的页面。
    • 前端渲染:数据在前端填充,即模板与数据的拼接操作是在用户的浏览器进行的。第一次打开页面时,客户端向服务器端发送 URL,服务器端返回所有页面的模板,渲染的时候根据当前需要哪些数据再向服务器端请求数据;第二次打开页面时,直接用 JS 刷新当前页面,不一定会向后端发送请求。

2. Route组件

Route 组件可以让我们的前端页面也可以和 URL 唯一对应起来,使得前端渲染的模式看起来假装和后端渲染是一样的。

我们创建一个新的项目 route-app,然后用 VS Code 打开项目:

create-react-app route-app

配置一下环境:

  • VS Code 安装插件:Auto Import - ES6, TS, JSX, TSX
  • 安装 Route 组件(在项目根目录下安装,安装好后重启一下 VS Code):npm i react-router-dom
  • 安装 Bootstrap:npm i bootstrap

Route 组件介绍:

  • BrowserRouter:所有需要路由的组件,都要包裹在 BrowserRouter 组件内;
  • Link:跳转到某个链接(但是没有向后端发请求),to 属性表示跳转到的链接;
  • Routes:类似于 C++ 中的 switch,但是只匹配第一个路径,即从前往后看每个 Route,判断当前链接是否等于 Route 中的链接,如果是则渲染 Route 中的组件,之后的就不继续往下判断了;
  • Route:路由,path 属性表示路径,element 属性表示路由到的内容(组件)。

我们先创建好我们项目的根组件 App、导航栏 NavBar,以及多个子页面的组件:HomeLinuxDjangoWebNotFound

NavBar 代码如下:

import React, { Component } from 'react';class NavBar extends Component {state = {  } render() {return (<nav className="navbar navbar-expand-lg bg-body-tertiary"><div className="container-fluid"><a className="navbar-brand" href="/">讲义</a><button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation"><span className="navbar-toggler-icon"></span></button><div className="collapse navbar-collapse" id="navbarNavAltMarkup"><div className="navbar-nav"><a className="nav-link active" aria-current="page" href="/">Home</a><a className="nav-link" href="/linux">Linux</a><a className="nav-link" href="/django">Django</a><a className="nav-link" href="/web">Web</a></div></div></div></nav>);}
}export default NavBar;

App 代码如下:

import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import NotFound from './notfound';class App extends Component {state = {  } render() {return (<React.Fragment><NavBar /></React.Fragment>);}
}export default App;

HomeLinuxDjangoWebNotFound 代码类似,只展示一个:

import React, { Component } from 'react';class Home extends Component {state = {  } render() {return (<h1>Home</h1>);}
}export default Home;

现在我们根据 URL 来渲染页面,注意此时还是属于后端渲染,每次都会重新加载页面,我们修改 App

import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import NotFound from './notfound';
import { Routes, Route } from 'react-router-dom'class App extends Component {state = {  } render() {return (<React.Fragment><NavBar /><Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route<Route path='/' element={<Home />} />  // 如果链接为'/'就跳到Home组件<Route path='/linux' element={<Linux />} /><Route path='/django' element={<Django />} /><Route path='/web' element={<Web />} /></Routes></React.Fragment>);}
}export default App;

现在我们用 Link 替换 NavBar 中的链接标签 a,这样就变为了前端渲染:

import React, { Component } from 'react';
import { Link } from 'react-router-dom'class NavBar extends Component {state = {  } render() {return (<nav className="navbar navbar-expand-lg bg-body-tertiary"><div className="container-fluid"><Link className="navbar-brand" to="/">讲义</Link><button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation"><span className="navbar-toggler-icon"></span></button><div className="collapse navbar-collapse" id="navbarNavAltMarkup"><div className="navbar-nav"><Link className="nav-link" aria-current="page" to="/">Home</Link><Link className="nav-link" to="/linux">Linux</Link><Link className="nav-link" to="/django">Django</Link><Link className="nav-link" to="/web">Web</Link></div></div></div></nav>);}
}export default NavBar;

3. URL中传递参数

当网站的页面数量很多的时候,我们肯定不可能去写那么多个 Route

假设我们现在有几篇 Web 讲义,第 i i i 篇的路由链接为:/web/content/i

import React, { Component } from 'react';
import { Link } from 'react-router-dom'class Web extends Component {state = {webs: [{id: 1, title: 'HTML基础标签'},{id: 2, title: 'CSS'},{id: 3, title: 'JavaScript'},{id: 4, title: '中期项目-拳皇'},{id: 5, title: 'React'},]} render() {return (<React.Fragment><h1>Web</h1><hr /><div>{this.state.webs.map(web => (<div key={web.id}><Link to={`/web/content/${web.id}`}>{web.id + '.' + web.title}</Link></div>))}</div></React.Fragment>);}
}export default Web;

我们先实现一下讲义内容的组件 WebContent

import React, { Component } from 'react';class WebContent extends Component {state = {  } render() {return (<h1>Web Content</h1>);}
}export default WebContent;

然后在 App 中写一下路由(我们不能写多个 <Route path='/web/content/i' element={<WebContent />} />,而是用 :xxx):

import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import WebContent from './webcontent';
import NotFound from './notfound';
import { Routes, Route } from 'react-router-dom'class App extends Component {state = {  } render() {return (<React.Fragment><NavBar /><div className='container'><Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route<Route path='/' element={<Home />} />  // 如果链接为'/'就跳到Home组件<Route path='/linux' element={<Linux />} /><Route path='/django' element={<Django />} /><Route path='/web' element={<Web />} /><Route path='/web/content/:chapter' element={<WebContent />} /></Routes></div></React.Fragment>);}
}export default App;

现在我们如何在 WebContent 中获取 :chapter 参数呢?先看一下函数组件获取参数的方式,可以直接用 useParams 函数获取参数:

import React from 'react';
import { useParams } from 'react-router-dom';const WebContent = () => {console.log(useParams())return (<h1>Web Content - {useParams().chapter}</h1>);
}export default WebContent;

如果是类组件的话就需要先套一层函数组件,然后把 useParams 函数作为参数传给自己:

import React, { Component } from 'react';
import { useParams } from 'react-router-dom';class WebContent extends Component {state = {  } render() {console.log(this.props.params)return (<h1>Web Content - {this.props.params.chapter}</h1>);}
}export default (props) => (<WebContent{...props}  // 先把函数组件里面的属性展开params={useParams()}/>
);

4. Search Params传递参数

如果网站链接形式为:/web/content?chapter=3,这样的链接也可以获取参数。

我们先改一下 Web 中的链接形式:

import React, { Component } from 'react';
import { Link } from 'react-router-dom'class Web extends Component {state = {webs: [...]} render() {return (<React.Fragment><h1>Web</h1><hr /><div>{this.state.webs.map(web => (<div key={web.id}><Link to={`/web/content?chapter=${web.id}`}>{web.id + '.' + web.title}</Link></div>))}</div></React.Fragment>);}
}export default Web;

然后在 WebContent 中获取链接的参数:

import React, { Component } from 'react';
import { useSearchParams } from 'react-router-dom';
import { Link } from 'react-router-dom'class WebContent extends Component {state = {searchParams: this.props.params[0],  // 用于获取某一个参数setSearchParams: this.props.params[1],  // 用于设置链接里的参数,重新渲染页面};render() {console.log(this.state.searchParams.get('chapter'))return (<React.Fragment><h1>Web Content - {this.state.searchParams.get('chapter')}</h1><hr /><div>讲义内容</div><hr /><Link to='/web'>返回上一级</Link></React.Fragment>);}
}export default (props) => (<WebContent{...props}  // 先把函数组件里面的属性展开params={useSearchParams()}/>
);

函数组件的写法如下:

import React from 'react';
import { useSearchParams } from 'react-router-dom';
import { Link } from 'react-router-dom'const WebContent = () => {let [searchParams, setSearchParams] = useSearchParams();console.log(searchParams.get('chapter'));return (<React.Fragment><h1>Web Content - {searchParams.get('chapter')}</h1><hr /><div>讲义内容</div><hr /><Link to='/web'>返回上一级</Link></React.Fragment>);
}export default WebContent;

5. 重定向

当打开一个不存在的链接时应该重定向到 404 Not Found,我们先将这个路由定义出来:<Route path='/404' element={<NotFound />} />

使用 Navigate 组件可以重定向,我们可以使用通配符 * 匹配其余的所有路径,然后将其重定向到 /404 页面即可:

import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import WebContent from './webcontent';
import NotFound from './notfound';
import { Routes, Route, Navigate } from 'react-router-dom'class App extends Component {state = {  } render() {return (<React.Fragment><NavBar /><div className='container'><Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route<Route path='/' element={<Home />} />  // 如果链接为'/'就跳到Home组件<Route path='/linux' element={<Linux />} /><Route path='/django' element={<Django />} /><Route path='/web' element={<Web />} /><Route path='/web/content' element={<WebContent />} /><Route path='/404' element={<NotFound />} /><Route path='*' element={<Navigate replace to='/404' />} /></Routes></div></React.Fragment>);}
}export default App;

6. 嵌套路由

假设 Linux 组件中有两个子模块 HomeworkTerminal,我们可以在 App 中创建嵌套路由:

import React, { Component } from 'react';
import NavBar from './navbar';
import Home from './home';
import Linux from './linux';
import Django from './django';
import Web from './web';
import WebContent from './webcontent';
import NotFound from './notfound';
import { Routes, Route, Navigate } from 'react-router-dom'class App extends Component {state = {  } render() {return (<React.Fragment><NavBar /><div className='container'><Routes>  // 一定要将路由包含在Routes里面,里面会有很多个Route<Route path='/' element={<Home />} />  // 如果链接为'/'就跳到Home组件<Route path='/linux' element={<Linux />}><Route path='homework' element={<h4>Homework</h4>} /><Route path='terminal' element={<h4>Terminal</h4>} /></Route><Route path='/django' element={<Django />} /><Route path='/web' element={<Web />} /><Route path='/web/content' element={<WebContent />} /><Route path='/404' element={<NotFound />} /><Route path='*' element={<Navigate replace to='/404' />} /></Routes></div></React.Fragment>);}
}export default App;

但是现在执行网页 /linux/homework 时不会渲染出子路由的内容,我们需要在父组件中添加 <Outlet /> 组件,用来填充子组件的内容:

import React, { Component } from 'react';
import { Link, Outlet } from 'react-router-dom'class Linux extends Component {state = {  } render() {return (<React.Fragment><h1>Linux</h1><hr /><ul className="nav justify-content-center"><li className="nav-item"><Link className="nav-link" to="/linux/homework">Homework</Link></li><li className="nav-item"><Link className="nav-link" to="/linux/terminal">Terminal</Link></li></ul><hr /><Outlet /></React.Fragment>);}
}export default Linux;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/74508.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序 wx:if使用

在微信小程序中&#xff0c;可以使用wx:if指令来控制某个元素是否需要被渲染到页面上。根据条件表达式的结果&#xff0c;wx:if指令决定元素是否显示。 下面是使用wx:if的基本示例&#xff1a; <view><view wx:if"{{condition}}"><!-- 条件为真时显…

计算机网络概述

目录 一、计算机网络的作用及互联网概述 1.1计算机网络在信息时代中的作用 1.2基本概念 1.3互联网基础架构发展三个阶段 1.4互联网的标准化工作 二、互联网的组成 2.1互联网组成 2.2互联网的边缘部分 2.3互联网的核心部分 三、计算机网络的类别 3.1计算机网络的定义:…

yapi以及gitlab的容器化部署

yapi部署&#xff1a; https://blog.csdn.net/Chimengmeng/article/details/132074922 gitlab部署 使用docker-compose.yml version: 3 services: web: image: twang2218/gitlab-ce-zh:10.5 restart: always hostname: 192.168.xx.xx environm…

企业架构LNMP学习笔记19

Nginx 第三方模块的使用&#xff1a; Nginx官方没有的功能&#xff0c;开源开发人员定制开发了一些功能&#xff0c;把代码公布出来&#xff0c;可以通过编译加载第三方模块的方式&#xff0c;使用新功能。 NGINX 3rd Party Modules | NGINX shell > tar xvf ngx-fancyinde…

IDEA中的MySQL数据库所需驱动包的下载和导入方法

文章目录 下载驱动导入方法 下载驱动 MySQL数据库驱动文件下载方法&#xff1a; 最新版的MySQL版本的驱动获取方法&#xff0c;这个超链接是下载介绍的博客 除最新版以外的MySQL版本的驱动获取方法&#xff0c;选择Platform Independent&#xff0c;选择第二个zip压缩包虾藻…

剑指 Offer 12. 矩阵中的路径

剑指 Offer 12. 矩阵中的路径 推荐写法 把判断条件都写在dfs函数开头&#xff08;对节点进行处理&#xff0c;尽量不要对边进行处理&#xff09; 写法一 class Solution {boolean[][] vis;public boolean exist(char[][] board, String word) {int m board.length, n boa…

浅谈redis未授权漏洞

redis未授权漏洞 利用条件 版本比较高的redis需要修改redis的配置文件&#xff0c;将bind前面#注释符去掉&#xff0c;将protected-mode 后面改为no 写入webshell config get dir #查看redis数据库路径 config set dir web路径# #修改靶机Redis数据库路径 config set dbfilen…

QT QTabWidget 控件 使用详解

本文详细的介绍了QTabWidget控件的各种操作&#xff0c;例如&#xff1a;新建界面、设置页面名字、设置提示信息、设置页面激活、设置标题栏位置、设置页面关闭按钮、设置页面关闭按钮、获取页面下标、获取页面总数、清空所有页面、删除某个页面、设置拖拽移动、设置显示页面、…

【Spring容器的启动流程】

Spring容器的启动流程主要分为以下几个步骤&#xff1a; 加载配置文件&#xff1a;Spring容器会从指定的配置文件中读取配置信息&#xff0c;包括bean的定义、依赖关系、AOP切面等。 创建容器&#xff1a;Spring容器启动后会创建一个容器实例&#xff0c;容器负责管理bean的生…

MyBatis-Plus排除不必要的字段

查询学生信息排除年龄列表 &#x1f4da;&#x1f50d; 使用MyBatis-Plus排除某些字段。如果你想要进行查询&#xff0c;但又不需要包含某些字段&#xff0c;那么这个功能将非常适合你。&#x1f50d;&#x1f393;&#x1f4dd; 1. 学生信息查询-排除年龄列表 在使用 MyBat…

【计算机网络】HTTP(下)

本文承接上文的代码进行改造&#xff0c;上文链接&#xff1a;HTTP上 文章目录 1. 实现网站跳转实现 自己的网站跳转 2. 请求方法(get) && 响应方法(post)GET方法POST方法GET与POST的应用场景 3. HTTP状态码在自己设计的代码中发现4043开头的状态码(重定向状态码)永久…

一种基于注意机制的快速、鲁棒的混合气体识别和浓度检测算法,配备了具有双损失函数的递归神经网络

A fast and robust mixture gases identification and concentration detection algorithm based on attention mechanism equipped recurrent neural network with double loss function 摘要 提出一个由注意力机制组成的电子鼻系统。首先采用端到端的编码器译码器&#xff…

容器编排学习(二)镜像制作和私有仓库介绍

一 Dockerfile 1 概述 commit的局限 很容易制作简单的镜像&#xff0c;但碰到复杂的情况就十分不方便例如碰到下面的情况需要设置默认的启动命令需要设置环境变量需要指定镜像开放某些特定的端口 Dockerfile就是解决这些问题的方法 Dockerfile是一种更强大的镜像制作方式…

VMware虚拟机+Centos7 配置静态,动态IP

本章目录 一、查看网关&#xff1a; 编辑–>虚拟网络编辑器二、点击NAT设置三、记住网关IP待会要用四、配置静态ip地址1、进入存放修改IP地址的目录2、修改ip地址的文件3、编辑文件4、文件&#xff08;编辑好后退出&#xff09; 五、重启网络六、测试1、linux上查看IP地址的…

爬虫爬取mp3文件例子

相信训练模型时数据集的获取也是一个很头疼的事情&#xff0c;搞cv领域的可以扛着摄像头架起三脚架拍摄获取&#xff08;以前干过&#xff09;&#xff0c;但是如果是nlp领域的呢&#xff0c;特别是chatgpt等大模型出来后对这类文本等数据的需求更大&#xff0c;如果没有现成的…

【AIGC专题】Stable Diffusion 从入门到企业级实战0403

一、前言 本章是《Stable Diffusion 从入门到企业级实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》第03节&#xff0c; 利用Stable Diffusion ControlNet Canny模型精准控制图像生成。本部分内容&#xff0c;位于整个Stable Diffusion生态…

JavaScript 数组中常用的方法

添加 push&#xff1a;数组末尾添加unshift&#xff1a;数组首位添加splice(1, 0, ‘新增内容’)&#xff1a;再指定位置插入&#xff0c;第二参数为0&#xff0c;表示新增&#xff1b;大于0&#xff0c;表示修改 删除 pop&#xff1a;删除末尾shift&#xff1a;删除首位slice(…

安全学习DAY23_CookieSessionToken

文章目录 Cookie和Session的区别Token的作用 Cookie和Session的区别 Cookie和Session都是用来在Web应用程序中跟踪用户状态的机制 1、存储位置不同&#xff1a; Cookie是存储在客户端&#xff08;浏览器&#xff09;上的&#xff0c;而Session是存储在服务器端的。 2、安全…

王道数据结构编程题 二叉树

二叉树定义 以下为本文解题代码的二叉树定义。 struct TreeNode {int val;TreeNode* left, *right;TreeNode(int val 0, TreeNode* left nullptr, TreeNode* right nullptr): val(val), left(left), right(right) {} };非递归后序遍历 题目描述 编写后序遍历二叉树的非递…

网络编程day6——基于C/S架构封装的线程池

一、线程竞争基本概念 竞争与同步 同一个进程中的线程共享进程中的绝大多数资源&#xff0c;当它们随意竞争时可能会导致资源被破坏、脏数据、不完整问题 通过一些手段让线程在竞争资源时相互协调、避免出现以上问题&#xff0c;这就称为线程同步 原子操作&#xff1a; 操作过程…