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;

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

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

相关文章

Android笔记(三十一):FrameLayout遇到的坑

背景 当FrameLayout里面是match_parent的时候&#xff0c;如果FrameLayout是wrap_content,则里面的view也会被当作wrap_content处理 原因 FrameLayout内的measureChildWithMargins -> getChildMeasureSpec的子类的MeasureSpec确定规则由父类的MeasureSpec和子类的LayoutP…

爬虫学习3

防盗链 #1.拿到conyId #2.拿到videoStatus返回的json.->srURL #srcURL里面的内容进行整理 #下载视频import requestsurl "https://www.pearvideo.com/video_1797054" contId url.split("_")[1]videoStatusUrl f"https://www.pearvideo.com/vi…

字典学习python

字典中的健可以添加&#xff0c;删除&#xff0c;但是不可以修改&#xff0c;只可以改后面的值 修改 字典名称[] value 若不存在健&#xff0c;那就添加&#xff0c;否则修改 pop删除&#xff0c;根据key实现对键值对&#xff0c;返回值是对应的value popitem返回值是一整个键…

QT-C++ 西门子snap7通讯库接口

QT-C 西门子snap7通讯库接口 一、核心程序1.头文件2.源文件 二、下载连接 一、核心程序 1.头文件 #pragma once #include <QObject> #include <QMutex> #include <QThread> #include "ToolSnapGlobal.h" #include "snap7.h" /* 特别说…

【设计模式】结构型模式(一):适配器模式、装饰器模式

结构型模式&#xff08;一&#xff09;&#xff1a;适配器模式、装饰器模式 1.适配器模式&#xff08;Adapter&#xff09;2.装饰器模式&#xff08;Decorator&#xff09;2.1 主要特点2.2 组成部分2.3 示例代码2.3.1 Component 组件2.3.2 ConcreteComponent 具体组件2.3.3 Dec…

认识物联网

新一代信息技术 物联网 物物相连的互联网&#xff0c;即物联网&#xff0c;又称传感器常见的传感器 • 温度传感器 • 压力传感器 • 声音传感器 • 02 • */08521 物联网概念 • 通过射频识别&#xff0c;红外传感器&#xff0c;全球定位系统GPS&#xff0c;激光扫描…

iOS 再谈KVC、 KVO

故事背景&#xff1a;大厂面试&#xff0c;又问道了基本的kvc kvo的原理和使用&#xff0c;由于转了前端&#xff0c;除了个setter和getter&#xff0c;我全忘记了&#xff0c;其实还是没有理解记忆&#xff0c;下面再看一下kvc 和kvo ,总结一个让人通过理解而无法忘记的方法&a…

07.适配器模式设计思想

07.适配器模式设计思想 目录介绍 01.适配器模式基础 1.1 适配器模式由来1.2 适配器模式定义1.3 适配器模式场景1.4 适配器模式思考 02.适配器模式实现 2.1 罗列一个场景2.2 用例子理解适配器2.3 适配器基本实现2.4 如何选择适配器 03.适配器模式分析 3.1 类适配器案例3.2 对象…

C语言 | Leetcode 题解之第535题TinyURL的加密与解密

题目&#xff1a; 题解&#xff1a; typedef struct {int key;char *val;UT_hash_handle hh; } HashItem;HashItem *dataBase NULL;char* encode(char* longUrl) {srand(time(0));int key;HashItem * pEntry NULL;while (true) {key rand();pEntry NULL;HASH_FIND_INT(dat…

Linux:线程安全的单例模式

设计模式 设计模式听上去是个很高贵的名词&#xff0c;其实就是是一套 多数人知晓、被反复使用、经过分类编目的、代码设计经验的总结&#xff0c;简称&#xff1a;对于编程比较典的场景的解决方案 单例模式 单例模式就是其中一种设计模式&#xff0c;是设计模式里的创建型模…

基于qt vs下的视频播放

**在 VS 2022 和 Qt 环境下利用 FFmpeg 实现一个基础视频播放器&#xff0c;需要完成以下几个步骤&#xff1a; 准备工作&#xff1a; 下载并配置 FFmpeg。确保 FFmpeg 的库和头文件可供 VS 2022 项目使用。 配置 Qt 项目&#xff0c;并导入 FFmpeg 库。 项目结构&#xff1a…

Django ORM详解:事务与F、Q函数使用

事务 #事务 from django.db import transaction from django.db.models import F # 装饰器用法&#xff1a;transaction.atomic def viewfunc(request):# 这些代码会在一个事务中执行... # with用法 try:#开启事物之后只有在事物里面的代码都正确运行完成才会执行相应的操作wit…

【网络安全】揭示 Web 缓存污染与欺骗漏洞

未经许可,不得转载。 文章目录 前言污染与欺骗Web 缓存污染 DoS1、HTTP 头部超大 (HHO)2、HTTP 元字符 (HMC)3、HTTP 方法覆盖攻击 (HMO)4、未键入端口5、重定向 DoS6、未键入头部7、Host 头部大小写规范化8、路径规范化9、无效头部 CP-DoS10、HTTP 请求拆分Web 缓存污染与有害…

AI打造超写实虚拟人物:是科技奇迹还是伦理挑战?

内容概要 在这个科技飞速发展的时代&#xff0c;超写实虚拟人物仿佛从科幻小说中走进了我们的日常生活。它们以生动的形象和细腻的动作&#xff0c;不仅在影视、广告和游戏中吸引了无数目光&#xff0c;更让我们对AI技术的未来充满了期待和疑惑。这些数字化身在逼真的外貌下&a…

第三次RHCSA作业

1、配置网络&#xff1a;为网卡添加一个本网段IPV4地址&#xff0c;x.x.x.123 2、配置yum本地仓库&#xff0c;并完成traceroute命令的安装 yum库配置成功过后&#xff0c;显示这个报错&#xff0c;没能写完 3、用至少两种方法查看sshd服务的进程号 4、添加一块10G大小的磁盘&…

前端用docker部署

1、环境检查 首先需要确认服务器上是否已经安装docker了。 在服务器上执行docker -v 显示对应的版本号说明已经安装好了docker 2、部署 使用Docker部署若依项目的前端服务&#xff0c;我们最终实现的是&#xff1a;启动一个镜像&#xff0c;我们的整个前端就启动了&#xf…

【Python开发】大模型应用开发项目整理

不知不觉已经入职3个月了&#xff0c;同事很好&#xff0c;工作充实&#xff0c;学到了很多东西&#xff0c;大大小小的需求也实现了接近20个。负责2个主要component&#xff0c;数据抓取和利用GenAI做数据提取。 1 背景 提取新闻中事件关键信息&#xff0c;比如人名&#xff…

论文翻译:ICLR 2024.DETECTING PRETRAINING DATA FROM LARGE LANGUAGE MODELS

文章目录 检测大型语言模型的预训练数据摘要1 引言2 预训练数据检测问题2.1 问题定义和挑战2.2 WIKIMIA&#xff1a;动态评估基准 3 MIN-K% PROB&#xff1a;简单的无参考预训练数据检测方法4 实验4.1 数据集和指标4.2 基线检测方法4.3 实现和结果4.4 分析 5 案例研究&#xff…

使用Jest进行JavaScript单元测试

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 使用Jest进行JavaScript单元测试 引言 Jest 简介 安装 Jest 创建基本配置 编写测试用例 运行测试 快照测试 模拟函数 代码覆盖率…

根据关键字搜索商品API返回值解析:深入解析与代码实践

在电子商务和数据集成领域&#xff0c;API&#xff08;应用程序编程接口&#xff09;扮演着至关重要的角色。通过API&#xff0c;开发者可以访问和利用平台的数据资源&#xff0c;实现自动化和智能化的数据交互。本文将探讨如何根据关键字搜索商品API的返回值进行解析&#xff…