React + Vite + TypeScript + React router项目搭建教程
一、创建项目

运行项目

二、目录结构
项目目录:
├─node_modules //第三方依赖
├─public //静态资源(不参与打包)
└─src├─assets //静态资源├─components //组件├─config //配置├─http //请求方法封装├─layout //页面布局├─pages //页面├─routes //路由├─service //请求├─store //状态管理└─util //通用方法└─App.css└─App.tsx└─index.css└─main.tsx└─vite-env.d.ts
├─.eslinttrc.cjs
├─.gitignore
├─index.html //项目页面总入口
├─package.json
├─tsconfig.json //ts配置文件
├─tsconfig.node.json
├─vite.config.ts //vite配置文件
三、sass安装
1 安装
npm i sass -D
2 创建全局 scss 文件

3 引入

这里的additionalData改为
additionalData: `@import "./src/assets/styles/index.scss";`
4 修改这4个文件

index.css去掉
main.tsx 中 import './index.css' 去掉
app.css 变成 app.scss,内容只剩下,h1{ color:$red; }
app.tsx 代码如下
import './App.scss'function App() {return (<><h1>Vite + React</h1></>)
}export default App
sass成功,页面如下

四、写一个函数式组件和类组件
import './App.scss'// 函数式组件写法
// import React, { useState } from 'react';
// function Example() {
// const [count, setCount] = useState(0);
// return (
// <div>
// <p>You clicked {count} times</p>
// <button onClick={() => setCount(count + 1)}>
// Click me
// </button>
// </div>
// );
// }// 类组件写法
import React from 'react';
class Example extends React.Component<any, any> {constructor(props: any) {super(props);this.state = {count: 0}}render() {return (<div><p>You clicked {this.state.count} times</p><button onClick={() => this.setState({ count: this.state.count + 1 })}>Click me</button></div>);}
}function App() {return (<><h1>Vite + React</h1><Example></Example></>)
}export default App
五、路由
1 下载
npm install react-router-dom -S
新建3个页面

HashRouter路由(vue中的hash模式)
main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { HashRouter as Router } from 'react-router-dom';ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<React.StrictMode><Router><App /></Router></React.StrictMode>
)
app.tsx
import { Route, Routes, Link, useNavigate } from "react-router-dom";
import Login from "./pages/login";
import Home from "./pages/home";
import User from "./pages/user";
import './App.scss'function App() {const navigate = useNavigate();return (<div className="App">{/* 指定跳转的组件,to 用来配置路由地址 */}<Link to="/">首页</Link><br /><Link to="/user">用户</Link><br /><button onClick={() => navigate('/login')}> 登录 </button><hr />{/* 路由出口:路由对应的组件会在这里进行渲染 */}<Routes>{/* 指定路由路径和组件的对应关系:path 代表路径,element 代表对应的组件,它们成对出现 */}<Route path='/' element={<Home />}></Route><Route path='/user' element={<User />}></Route><Route path='/login' element={<Login />}></Route></Routes></div>)
}export default App
成功结果如下

BrowserRouter路由(vue中的history模式?)
main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import { BrowserRouter as Router } from 'react-router-dom';ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<React.StrictMode><Router><App /></Router></React.StrictMode>,
)
app.tsx
import { Route, Routes, Link, useNavigate } from "react-router-dom";
import Login from "./pages/login";
import Home from "./pages/home";
import User from "./pages/user";
import './App.scss'function App() {const navigate = useNavigate();return (<div className="App">{/* 指定跳转的组件,to 用来配置路由地址 */}<Link to="/">首页</Link><br /><Link to="/user">用户</Link><br /><button onClick={() => navigate('/login')}> 登录 </button><hr />{/* 路由出口:路由对应的组件会在这里进行渲染 */}<Routes>{/* 指定路由路径和组件的对应关系:path 代表路径,element 代表对应的组件,它们成对出现 */}<Route path='/' element={<Home />}></Route><Route path='/user' element={<User />}></Route><Route path='/login' element={<Login />}></Route></Routes></div>)
}export default App
嵌套路由
app.tsx
// 嵌套路由
import { Route, Routes, Link, useNavigate } from 'react-router-dom';
import Login from "./pages/login";
import Home from "./pages/home";
import User from "./pages/user";
import './App.scss'
function App() {const navigate = useNavigate();return (<div className="App">{/* 指定跳转的组件,to 用来配置路由地址 */}<Link to="/home">首页</Link><br /><Link to="/home/user">用户</Link><br /><button onClick={() => navigate('/home/login')}> 登录 </button>{/* 路由出口:路由对应的组件会在这里进行渲染 */}<Routes>{/* 指定路由路径和组件的对应关系:path 代表路径,element 代表对应的组件,它们成对出现 */}<Route path='/home' element={<Home />}><Route path='user' element={<User />}></Route><Route path='login' element={<Login />}></Route></Route></Routes></div>)
}
export default App
home.tsx
import { Outlet } from "react-router-dom";
function Home() {return (<div><div>home页面</div><Outlet /></div>);
}export default Home;
页面如下

重定向
import { Navigate } from 'react-router-dom';
<Route path='/' element={<Navigate to="/layout" />}></Route>
useRoutes路由配置
1 app.scss
h1{color:$red;
}body{padding: 0;margin: 0;width: 100vw;height: 100vh;
}
#root{padding: 0;margin: 0;width: 100vw;height: 100vh;
}
app.tsx
import GetRoutes from "./routes/index";
import './App.scss'function App() {return (<GetRoutes></GetRoutes>)
}
export default App
home.tsx
function Home() {return (<div>home页面</div>);
}
export default Home;
新增文件

routes/index.tsx 代码如下
import { useRoutes, Navigate, RouteObject } from "react-router-dom";import Layout from "../layout/index";
import Login from "../pages/login";
import Home from "../pages/home";
import User from "../pages/user";export const router_item: Array<object> = [{ path: "/", label: "首页", element: <Navigate to="/layout/home" /> },{path: "/layout",label: "控制台",element: <Layout />,children: [{path: "home",label: "首页",element: <Home />},{path: "login",label: "登录页",element: <Login />,},{path: "user",label: "用户页",element: <User />},],},
];function GetRoutes() {const routes: RouteObject[] = useRoutes(router_item);return routes;
}export default GetRoutes;
layout/index.tsx 代码如下
import { Outlet, Link } from "react-router-dom";
function Layout() {return (<><div style={{display: 'flex', width: '100%', height: '100%'}}><div style={{width: '200px', background: '#eee'}}><Link to="/layout/home">home 页</Link><br /><Link to="/layout/login">login 页</Link><br /><Link to="/layout/user">user 页</Link><br /></div><div style={{flex: '1'}}><Outlet /></div></div></>);
}
export default Layout;
页面成功如下

路由懒加载
有些页面比较大,我们可以使用懒加载,来提升页面加载性能,避免页面卡顿;react官网提供了路由懒加载的完整实例:react路由懒加载。懒加载主要借助lazy、suspense组件来实现。
lazy 能够让你在组件第一次被渲染之前延迟加载组件的代码。<Suspense> 允许您显示临时组件(一般是一个loading状态),直到其子项完成加载。
修改 routes/index.tsx 代码如下
import { useRoutes, Navigate, RouteObject } from "react-router-dom";import Layout from "../layout/index";
import Login from "../pages/login";
import Home from "../pages/home";
import User from "../pages/user";import { lazy } from "react";
import lazyLoad from "./lazyLoad";
// 添加一个固定的延迟时间,以便你可以看到加载状态
function delayForDemo(promise: Promise<any>) {return new Promise(resolve => {setTimeout(resolve, 2000);}).then(() => promise);
}export const router_item: Array<object> = [{ path: "/", label: "首页", element: <Navigate to="/layout/home" /> },{path: "/layout",label: "控制台",element: <Layout />,children: [{path: "home",label: "首页",// element: <Home />element: lazyLoad(lazy(() => delayForDemo(import("../pages/home")))) //故意延迟2s,这里是延迟加载},{path: "login",label: "登录页",// element: <Login />,element: lazyLoad(lazy(() => import("../pages/login"))), //这里是延迟加载},{path: "user",label: "用户页",element: <User />},],},
];function GetRoutes() {const routes: RouteObject[] = useRoutes(router_item);return routes;
}export default GetRoutes;
增加文件

lazyLoad.tsx 代码如下
import { LazyExoticComponent, Suspense } from "react";
import Spinner from "../components/spinner";
/*** 实现路由懒加载* @param Comp 懒加载组件* @returns */
function lazyLoad(Comp: LazyExoticComponent<() => JSX.Element>) {return (<Suspense fallback={<Spinner />}><Comp /></Suspense>);
}export default lazyLoad;
spinner.tsx 代码如下
function Spinner() {return (<>loading...</>);
}export default Spinner;
相关文章:
React + Vite + TypeScript + React router项目搭建教程
一、创建项目 运行项目 二、目录结构 项目目录: ├─node_modules //第三方依赖 ├─public //静态资源(不参与打包) └─src├─assets //静态资源├─components //组件├─config //配置├─http //请求方法封装├─layout //页面…...
【ShuQiHere】️ 如何启用 SSH 服务
🛠️ 如何启用 SSH 服务 目录 基础概念 🌱检查是否已安装 SSH 服务 🔍在不同操作系统上安装 SSH 服务 💻 LinuxWindows 11macOS 启动和启用 SSH 服务 🚀配置防火墙以允许 SSH 连接 🔥配置 SSH 服务&#…...
【自动化测试】APP UI 自动化(安卓)-本地环境搭建
一、软件准备及版本介绍 软件版本JAVA-SDK1.8.0_181 python 3.10.10 Android SDK Tools 下最新版本即可,无特殊要求 PyCharm 2023.3.5(下最新版本即可,无特殊要求) 二、安装步骤及环境变量配置 2.1 Java安装及配置 1&am…...
java毕业设计之基于Bootstrap的常州地方旅游管理系统的设计与实现(springboot)
项目简介 基于Bootstrap的常州地方旅游管理系统的设计与实现有下功能: 基于Bootstrap的常州地方旅游管理系统的设计与实现的主要使用者分为用户功能模块和管理员功能模块两大部分,用户可查看景点信息、景点资讯等,注册登录后可进行景点订票…...
《机甲崛起》
第一章:觉醒 在遥远的未来,地球的面貌已被人类科技彻底改变。蓝天被高耸的摩天大楼和闪烁的飞行器撕裂,城市的光辉仿佛能照亮整个星球。然而,繁华背后隐藏着深重的危机:生态环境的恶化、资源的匮乏,已成为…...
Windows10:Linux Reader
Linux Reader Access files and folders on Ext, UFS, HFS, ReiserFS, or APFS file systems from Windows DiskInternals 发布的 Linux Reader 是一款能在 Windows 系统环境下读取 Linux 分区文件的免费软件,提供了资源管理器式的浏览模式。它使用只读模式挂载 L…...
一、k8s快速入门之学习Kubernetes组件基础
一、三个容器管理器平台 Apache MESOS 开源的分布式资源管理框架,被推特选为基础平台,2019年推特换位k8s,MESOS最新版可以在MESOS上管理k8sDOCKER SWARM docker总部发行的,实现docker的集群方案,和docker捆版一起&…...
PostgreSQL 到 PostgreSQL 数据迁移同步
简述 PostgreSQL 是一个历史悠久且广泛使用的数据库,不仅具备标准的关系型数据库能力,还具有相当不错的复杂 SQL 执行能力。用户常常会将 PostgreSQL 应用于在线事务型业务,以及部分数据分析工作,所以 PostgreSQL 到 PostgreSQL …...
RestTemplate 常用方法(提供了多种方法来发送 HTTP 请求)
RestTemplate 是 Spring 框架中用于同步客户端 HTTP 请求的一个类,它提供了多种方法来发送 HTTP 请求。以下是一些常用的 RestTemplate 方法及其代码案例: 1.postForObject() 该方法用于发送 POST 请求,并期望返回一个对象。以下是一个使用…...
常量和变量
常量 常量是指在程序中使用的一些具体的数、字符。在程序运行过程中,其值不能被更改。如123,145.88,m,TRUE等。常量,用于记录程序中不可更改的数据。 分类 1、整型常量,表示整数的常量。 表示形式: 1)十进制形…...
Go语言的使用
在安装Go和配置镜像时,可以根据操作系统和网络环境来选择适合的步骤。以下是详细的安装步骤和镜像配置: 1. 安装Go 1.1 通过官方下载 访问 Go的官方下载页面 下载适合操作系统的安装包(Windows、macOS 或 Linux)。安装包下载完…...
详解CRC校验原理以及FPGA实现
文章目录 一、什么是CRC校验?二、实现CRC校验原理以及步骤2.1 用多项式表示二元码数据2.2 选择一个生成多项式作为校验2.3 计算CRC校验码 三、CRC判断数据是否错误的原理以及步骤3.1 将收到的数据与生成多项式求余3.2 数据发生错误再进行CRC校验判断 四、FPGA实现CR…...
企业如何通过架构蓝图实现数字化转型
数字化转型的关键——架构蓝图的力量 在当今的商业世界,数字化转型已经不再是一个选择,而是企业生存与发展不可回避的战略行动。企业希望通过数字化提高效率、增强灵活性,并为客户提供更好的体验。然而,数字化转型不仅仅涉及技术…...
React第十三章(useTransition)
useTransition useTransition 是 React 18 中引入的一个 Hook,用于管理 UI 中的过渡状态,特别是在处理长时间运行的状态更新时。它允许你将某些更新标记为“过渡”状态,这样 React 可以优先处理更重要的更新,比如用户输入&#x…...
IDEA使用Maven Helper查看整个项目的jar冲突
在插件市场安装Maven Helper,安装好后,重启IDEA;双击打开可能存在jar冲突的pom文件;在右侧面板查看冲突,text是引入的依赖明细,点击Dependecy Analyzer选项卡即可查看冲突的jar。...
uniapp项目 存储数据到手机本地
打开manifest.json,在App权限配置中,添加读取和写入的权限 <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name"android.permission.WRITE_EXTERNAL_STORAGE"/&g…...
景联文科技医疗数据处理平台:强化医疗数据标注与管理,推动医疗数字化新篇章
随着医疗科技快速进步与广泛应用,医疗信息的规模正在迅速扩张,如何有效管理这些医疗数据成为了关键议题。 医疗数据不仅包括传统的纸质病历,还有电子病历、实验室检测结果、医学影像等多样化的数字信息。为确保这些数据能为临床决策、科研分析…...
vue使用高德地图实现轨迹显隐
<template><div><el-button type"primary" click"pathShowOrHide">轨迹显/隐</el-button><div id"container" /></div> </template><script> import AMapLoader from amap/amap-jsapi-loaderex…...
Maven(20) 如何使用Maven进行版本管理?
Maven提供了一套强大的版本管理机制,允许开发者管理项目的版本号,并在不同的版本之间进行升级和降级。以下是如何使用Maven进行版本管理的详细步骤和代码示例: 步骤 1: 定义项目版本 在pom.xml文件中,你需要定义项目的版本号。版…...
AWS RDS MySQL内存使用
1. AWS RDS所拥有的内存(实例类型),和数据库能够使用的内存是不同的。RDS实例为操作系统和 RDS 管理进程预留了内存,数据库使用内存大小,小于数据库实例类的硬件规格中所示的值(以 GiB 为单位)[…...
云英谷开启招股:拟募资11亿港元 5月27日上市 小米华为红杉是股东
雷递网 雷建平 5月18日云英谷科技股份有限公司(简称:“云英谷”,股票代码:“03310”)日前开启招股,准备2026年5月27日在港交所上市。云英谷发行价为20.81港元,发行5285.92万股,募资总…...
Hi3861点灯程序背后的构建系统:手把手教你修改BUILD.gn文件,定制你的第一个鸿蒙应用
Hi3861开发实战:深入鸿蒙构建系统与GN脚本定制指南 当LED灯在Hi3861开发板上第一次亮起时,很多开发者会认为这只是一个简单的GPIO控制实验。但鲜为人知的是,这个看似简单的"点灯"动作背后,隐藏着鸿蒙轻量设备开发中最核…...
犀牛开发者日记-犀牛论剑特辑 | 李江浩:一个 ROS 布道师的转身
熟悉ROS领域的朋友,对李江浩这个名字想必并不陌生。作为资深ROS布道师,他常年活跃在技术社区分享干货,面对同行提出的各类问题,总能给出快准狠的解决方案,精准直击技术痛点。熟悉他的人都有一个共同感受:李…...
卡尔曼滤波:从噪声数据中提取最优估计的核心算法
1. 项目概述:从“猜”到“算”的智慧如果你曾经尝试过用手机导航,或者玩过需要控制无人机、机器人的游戏,甚至只是好奇自动驾驶汽车是如何“看清”这个世界的,那么你很可能已经间接接触过卡尔曼滤波。这个名字听起来有点高深&…...
SharpCompress实战:一个方法搞定C#里ZIP压缩打包,附赠RAR/7Z解压和TAR.GZ创建教程
C#压缩解压全能手册:用SharpCompress玩转ZIP/RAR/7Z/TAR.GZ 在开发日志管理系统、文件上传模块或数据备份工具时,文件压缩解压功能就像空气一样不可或缺。但面对ZIP、RAR、7Z、TAR.GZ这些格式各异的压缩包,不少开发者都会陷入API选择的困境。…...
Godot-MCP终极指南:如何用AI助手5倍提升Godot游戏开发效率
Godot-MCP终极指南:如何用AI助手5倍提升Godot游戏开发效率 【免费下载链接】Godot-MCP An MCP for Godot that lets you create and edit games in the Godot game engine with tools like Claude 项目地址: https://gitcode.com/gh_mirrors/god/Godot-MCP 在…...
别再为模型格式发愁了!实测Revit插件一键转GLB/DAE/STL等格式的完整流程
Revit模型高效转换实战:从格式选型到跨平台协作的全流程指南 在建筑信息模型(BIM)工作流中,Revit作为行业标准工具,其模型往往需要与不同领域的协作方共享。Web开发者需要GLB格式用于网页展示,3D打印服务商…...
Claude Code用户如何通过Taotoken解决封号与Token不足的困扰
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Claude Code用户如何通过Taotoken解决封号与Token不足的困扰 1. 理解Claude Code的接入限制与Taotoken的解决方案 Claude Code作为…...
Perplexity接入知网文献搜索的5大避坑指南:实测发现92%研究者正在浪费87%检索时间
更多请点击: https://intelliparadigm.com 第一章:Perplexity接入知网文献搜索的底层逻辑与认知重构 Perplexity 作为基于大语言模型的实时问答引擎,其核心能力并非仅依赖于内部参数化知识,而是通过动态检索增强生成(…...
Inter字体终极指南:为什么这款开源字体能重新定义数字界面设计
Inter字体终极指南:为什么这款开源字体能重新定义数字界面设计 【免费下载链接】inter The Inter font family 项目地址: https://gitcode.com/gh_mirrors/in/inter Inter字体是一款专为现代数字屏幕设计的开源无衬线字体,通过科学优化的字形设计…...
