react-问卷星项目(5)
实战
路由
- 路由设计,网址和页面的关系,就是从业务上分析需要哪些页面哪些页面内容可以抽离,业务流程要有入有出
- 增加页面和Layout模版,模版就是抽离页面公共部分,比如都有顶部或者左侧导航,直接上代码,就是组件复用的思想
- 使用React-router增加路由配置(目前路由模块只有这一个工具)
React-router
路由工具
其中Outlet和vue中的slot插槽相似,通过下载路由并导入获得
下载React-router
npm install react-router-dom --save
这一篇实战性比较强,直接上代码,相关部分在代码中都有注释
项目的目录结构如下,components是存放组件,Layouts存放布局,布局就是页面抽离出的公共部分,比如几个几个页面都有顶部和底部,这两个就可以抽出来成布局,pages存放页面,在React中都是组件,但是在业务上我们称之为页面,结构就是右边这个图所示,有点模糊凑合着看,从老师的视频里截出来的
全部先新建出来后按照下面的格式先布局就可以。
// 星标问卷页面
import React, { FC } from "react";
const Star: FC = () => {return <p>Star</p>;
};
export default Star;
接下来一个个页面开始细化,基本思路就是先list文件挂载到app中,然后添加问卷列表卡片组件Question,再然后完善布局,其中布局有些注意点就是,一部分是固定的,但是还有一部分是可以切换的,可以切换的这一块需要用的路由的一个类,下面碰到的时候会注释。
ps:新项目记得把sass之类的下载好,忘记指令的可以看这篇,反正什么报错下载什么就可以
List.tsx
import React, { FC, useState } from "react";
import { useSearchParams } from "react-router-dom";
import QuestionCard from "../../components/QuestionCard";
import styled from "./List.module.scss";const rawQuestionList = [{_id: "q1",title: "问卷1",isPublished: true,isStar: false,answerCount: 5,createAt: "3月10日 13:23",},{_id: "q2",title: "问卷2",isPublished: false,isStar: true,answerCount: 15,createAt: "3月22日 13:23",},{_id: "q3",title: "问卷3",isPublished: true,isStar: true,answerCount: 100,createAt: "4月10日 13:23",},{_id: "q4",title: "问卷4",isPublished: false,isStar: false,answerCount: 98,createAt: "3月23日 13:23",},
];const List: FC = () => {const [searchParams] = useSearchParams();console.log("keyword", searchParams.get("keyword"));const [questionList, setQuestionList] = useState(rawQuestionList);return (<><div className={styled.header}><div className={styled.left}><h3>我的问卷</h3></div><div className={styled.right}>搜索</div></div><div className={styled.content}>{questionList.map((q) => {const { _id } = q;return <QuestionCard key={_id} {...q} />;})}</div><div className={styled.footer}>footer</div></>);
};export default List;
List.module.scss
.header{display: flex;.left{flex: 1;}.right{flex: 1;text-align: right;}
}.content{margin-bottom: 20px;
}.footer{text-align: center;
}body{background-color: #f1f1f1;
}
QuestionCard.tsx
import React, { FC, useEffect } from "react";
// import "./QuestionCard.css";
import styled from "./QuestionCard.module.scss";
import classnames from "classnames";
type PropsType = {_id: string;title: string;isPublished: boolean;isStar: boolean;answerCount: number;createAt: string;// 问号是可写可不写,跟flutter语法相似deletQuestion?: (id: string) => void;pubQuestion?: (id: string) => void;
};const QuestionCard: FC<PropsType> = (props: PropsType) => {const { _id, title, createAt, answerCount, isPublished } = props;return (<div className={styled.container}><div className={styled.title}><div className={styled.left}><a href="#">{title}</a></div><div className={styled.right}>{isPublished ? (<span style={{ color: "green" }}>已发布</span>) : (<span>未发布</span>)} <span>答卷:{answerCount}</span> <span>{createAt}</span></div></div><div className={styled["button-container"]}><div className={styled.left}><button>编辑问卷</button><button>数据统计</button></div><div className={styled.right}><button>标星</button><button>复制</button><button>删除</button></div></div></div>);
};export default QuestionCard;
QuestionCard.module.scss
.container{margin-bottom: 20px;padding: 12px;border-radius: 3px;background-color: white;&:hover{box-shadow: 0 4px 10px lightgray;}
}.title{display: flex;.left{flex: 1;}.right{flex: 1;text-align: right;}
}.button-container{display: flex;.left{flex: 1;}.right{flex: 1;text-align: right;button{color: #999;}}
}
下面开始就是布局文件,其中用到的Outlet和vue中的插槽比较相似,作用就是占位,可以实现切换组件的效果
MainLayout.tsx
import React, { FC } from "react";
import { Outlet } from "react-router-dom";
const MainLayout: FC = () => {return (<div><div>MainLayout header</div><div><Outlet /></div><div>MainLayout footer</div></div>);
};
export default MainLayout;
ManagerLayout.tsx
import React, { FC } from "react";
import { Outlet } from "react-router-dom";
import styled from "./MangerLayout.module.scss";
const MangerLayout: FC = () => {return (<div className={styled.container}><div className={styled.left}><p>MainLayout left</p><button>创建问卷</button><br /><a href="#">我的问卷</a><br /><a href="#">星标问卷</a><br /><a href="#">回收站</a><br /></div><div className={styled.right}><Outlet /></div></div>);
};
export default MangerLayout;
MangerLayout.module.scss
.container{display: flex;padding: 24px 0;width: 1200px;margin: 0 auto; // 水平居中.left{width: 120px;background-color: aqua;}.right{flex: 1;margin-left: 60px;background-color: aquamarine;}}
QuestionLayout.tsx
import React, { FC } from "react";
import { Outlet } from "react-router-dom";const QuestionLayout: FC = () => {return (<div><div>QuestionLayout header</div><div><Outlet /></div><div>QuestionLayout footer</div></div>);
};
export default QuestionLayout;
接下来是路由器编辑
router/index.tsx
// 路由配置
import React from "react";
import { createBrowserRouter } from "react-router-dom";
import MainLayout from "../Layouts/MainLayout";
import ManagerLayout from "../Layouts/ManagerLayout";
import QuestionLayout from "../Layouts/QuestionLayout";
import Home from "../pages/Home";
import Login from "../pages/Login";
import Register from "../pages/Register";
import NotFound from "../pages/NotFound";
import List from "../pages/manager/List";
import Trash from "../pages/manager/Trash";
import Star from "../pages/manager/Star";
import Edit from "../pages/manager/question/Edit";
import Static from "../pages/manager/question/Static";// 数组表示可以创建多路径
const router = createBrowserRouter([{path: "/",// 访问根目录时element指向MainLayoutelement: <MainLayout />,children: [{path: "/",element: <Home />,},{path: "login",element: <Login />,},{path: "register",element: <Register />,},{path: "manager",element: <ManagerLayout />,children: [{path: "list",element: <List />,},{path: "star",element: <Star />,},{path: "trash",element: <Trash />,},],},{// 以上页面都没有命中path: "*",element: <NotFound />,},{path: "question",element: <QuestionLayout />,children: [{path: "edit",element: <Edit />,},{path: "static",element: <Static />,},],},],},{path: "question",element: <QuestionLayout />,children: [{path: "edit/:id",element: <Edit />,},{path: "static/:id",element: <Static />,},],},
]);
export default router;
最后挂载到App上就可以
App.tsx
import { RouterProvider } from "react-router-dom";
import router from "./router";function App() {return <RouterProvider router={router}></RouterProvider>;
}export default App;
可以在路径上添加相应后缀尝试是否能正确切换,接下来就是传值和接收值的测试,包括使用路由进行页面跳转
Home.tsx
// 首页
import React, { FC } from "react";
import { useNavigate, Link } from "react-router-dom";const Home: FC = () => {const nav = useNavigate();function clickHandler() {nav({pathname: "/login", // 路径search: "b=21", // 路径附加参数,类似get});}return (<div><p>Home</p><div><button onClick={clickHandler}>登录</button><Link to="/register">注册</Link></div></div>);
};
export default Home;
Login.tsx
// 登陆页面
import React, { FC } from "react";
import { useNavigate } from "react-router-dom";const Login: FC = () => {const nav = useNavigate();return (<div><p>Login</p><div>{/* -1就是返回上一个 */}<button onClick={() => nav(-1)}>返回</button></div></div>);
};
export default Login;
Edit/index.tsx
// 编辑页面,页面比较复杂所以不放在单个页面,而是文件夹中
import React, { FC } from "react";
import { useParams } from "react-router-dom";const Edit: FC = () => {// 默认值,不传入就是空字符串const { id = "" } = useParams();return <p>Edit{id}</p>;
};
export default Edit;
question目录下的文件比较特别,需要跳转的时候传参,进行完上面的设置后可以在路径后面加入参数测试是否成功,如图所示
相关文章:

react-问卷星项目(5)
实战 路由 路由设计,网址和页面的关系,就是从业务上分析需要哪些页面哪些页面内容可以抽离,业务流程要有入有出增加页面和Layout模版,模版就是抽离页面公共部分,比如都有顶部或者左侧导航,直接上代码&…...
08.useInterval
在 React 应用中,实现定时器功能通常需要使用 setInterval() 和 clearInterval(),这可能会导致代码复杂和难以维护。useInterval 钩子提供了一种声明式的方法来实现定时器功能,使得定时器的管理更加简单和直观。这个自定义钩子不仅简化了定时器的使用,还解决了一些常见的定…...

【Android 源码分析】Activity生命周期之onDestroy
忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。 – 服装…...
增强现实中的物体识别与跟踪
增强现实(AR)中的物体识别与跟踪是实现虚拟内容与现实世界无缝融合的关键技术。以下是该领域的主要技术和方法概述: 1. 物体识别 1.1 特征提取 SIFT、SURF、ORB:传统的特征提取算法用于识别图像中的关键点并生成描述符…...
移动端实现下拉刷新和上拉加载(内含案例)
在前端开发中,上拉加载和下拉刷新常用于实现内容的动态加载,尤其在移动端的应用中。下面我将提供一个简单的示例和逻辑说明。 1. 逻辑说明: 下拉刷新: 用户向下拖动页面顶部,触发一个事件,刷新当前内容。需…...

Opencv第十一章——视频处理
1. 读取并显示摄像头视频 1.1 VideoCapture类 VideoCapture类提供了构造方法VideoCapture(),用于完成摄像头的初始化工作,其语法格式如下: capture cv2.VideoCapture(index) 参数说明: capture:要打开的摄像头视频。 index:摄像头设备索引。…...

Flutter 3.24 AAPT: error: resource android:attr/lStar not found.
在Android build,gradle下面,添加右边红框的代码: subprojects {afterEvaluate { project ->if (project.plugins.hasPlugin("com.android.application") ||project.plugins.hasPlugin("com.android.library")) {project.androi…...
C++——输入一个2*3的矩阵, 将这个矩阵向左旋转90度后输出。(要求:使用指针完成。)
没注释的源代码 #include <iostream> using namespace std; int main() { int a[2][3]; cout<<"请输入一个2*3的矩阵:"<<endl; for(int i0;i<2;i) { for(int j0;j<3;j) { cin>>a[i][j…...

AI芯片WT2605C赋能厨房家电,在线对话操控,引领智能烹饪新体验:尽享高效便捷生活
在智能家居的蓬勃发展中,智能厨电作为连接科技与生活的桥梁,正逐步渗透到每一个现代家庭的厨房中。蒸烤箱作为智能厨电的代表,以其丰富的功能和高效的性能,满足了人们对美食的多样化追求。然而,面对众多复杂的操作功能…...

详解调用钉钉AI助理消息API发送钉钉消息卡片给指定单聊用户
文章目录 前言准备工作1、在钉钉开发者后台创建一个钉钉企业内部应用;2、创建并保存好应用的appKey和appSecret,后面用于获取调用API的请求token;3、了解AI助理主动发送消息API:4、应用中配置好所需权限:4.1、权限点4.…...

57 长短期记忆网络(LSTM)_by《李沐:动手学深度学习v2》pytorch版
系列文章目录 文章目录 系列文章目录长短期记忆网络(LSTM)门控记忆元输入门、忘记门和输出门候选记忆元 (相当于RNN中计算 H t H_t Ht)记忆元隐状态 从零开始实现初始化模型参数定义模型训练和预测 简洁实现小结练习 长短期记忆网络(LSTM&a…...

Linux系统安装教程
Linux安装流程 一、前置准备工作二、开始安装Linux 一、前置准备工作 安装好VMWare虚拟机,并下载Linux系统的安装包; Linux安装包路径为:安装包链接 , 提取码为:4tiM 二、开始安装Linux...

Redis: Sentinel工作原理和故障迁移流程
Sentinel 哨兵几个核心概念 1 ) 定时任务 Sentinel 它是如何工作的,是如何感知到其他的 Sentinel 节点以及 Master/Slave节点的就是通过它的一系列定时任务来做到的,它内部有三个定时任务 第一个就是每一秒每个 Sentinel 对其他 Sentinel 和 Redis 节点…...

通信工程学习:什么是IGMP因特网组管理协议
IGMP:因特网组管理协议 IGMP(Internet Group Management Protocol,因特网组管理协议)是TCP/IP协议簇中负责组播成员管理的协议。它主要用于在用户主机和与其直接相连的组播路由器之间建立和维护组播组成员关系。以下是关于IGMP协议…...
高效批量导入多个SQL文件至SQL Server数据库的实用方法
当需要批量导入多个SQL文件到SQL Server数据库时,可以通过以下几种方法来实现: 方法一:使用SQLCMD命令行工具(亲测可用) 准备SQL文件:确保所有的SQL文件都位于同一个文件夹内,并且文件扩展名为…...

【树莓派系列】树莓派wiringPi库详解,官方外设开发
树莓派wiringPi库详解,官方外设开发 文章目录 树莓派wiringPi库详解,官方外设开发一、安装wiringPi库二、wiringPi库API大全1.硬件初始化函数2.通用GPIO控制函数3.时间控制函数4.串口通信串口API串口通信配置多串口通信配置串口自发自收测试串口间通信测…...
前端模块化CommonJs、ESM、AMD总结
前端开发模式进化史 前端工程化正是为了应对这些演化中出现的挑战和需求而发展起来的: 前后端混合:服务端渲染,javascript仅实现交互前后端分离:借助 ajax 实现前后端分离、单页应用(SPA)等新模式模块化开发:npm 管理…...

JavaWeb - 8 - 请求响应 分层解耦
请求响应 请求(HttpServletRequest):获取请求数据 响应(HttpServletResponse):设置响应数据 BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程…...
1G,2G,3G,4G,5G各代通信技术的关键技术,联系和区别
目录 1G2G3G4G5G各代通信技术的联系和区别联系区别 1G 1G的主要特点是无线移动化。关键技术为蜂窝组网,支持频率复用和移动切换,可以实现个人和个人移动状态下不间断的语音通信。 1G通信系统现已关闭,其主要缺点是串好和盗号。 2G 数字化…...

【宽搜】2. leetcode 102 二叉树的层序遍历
题目描述 题目链接:二叉树的层序遍历 根据上一篇文章的模板可以直接写代码,需要改变的就是将N叉树的child改为二叉树的left和right。 代码 class Solution { public:vector<vector<int>> levelOrder(TreeNode* root) {vector<vector&…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...

小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...