React实战项⽬开发完整流程含代码

React实战演练项⽬一需求分析及项目初始化

需求分析

刚学完React,开始找项目进行上手练习!
react+vite项目搭建

页面组件拆分:

头部:导航tab、搜索框、登录注册
中间:分类导航、轮播图、新人福利、高单价产品导航
课程分类列表、底部内容、登陆提示浮层、登录/注册弹窗

项目搭建

项目git初始化

git init

本地项目设置远程仓库地址

git remote add origin xxxx

通过npm创建react项目
vite创建react项目
使用vscode打开项目,然后安装相关依赖,运行项目

npm install
npm run dev

vite创建react项目
运行成功vite创建react项目
删除相关文件,创建首页文件,初始化项目,目录结构
vite创建react项目
创建首页项目,引入首页
react项目初始化

配置Ant-Design+Unocss

安装antDesign

npm install antd

引入并使用组件
react项目初始化
react项目初始化

什么是Unocss

unocss是一个即时的原子CSS引擎,它可以让你用简短的类名来控制元素的样式,而不需要写复杂的CSS代码。
当然,原子样式也有很多选择,最著名的就是 Tailwind。但由于Tailwind 会生成大量样式定义,会导致全量的 CSS
文件往往体积会多至数 MB,从而有性能上有一些不足。

unocss的优点

  • 它可以让你快速地开发和原型设计,而不需要考虑CSS的细节。
  • 它可以让你的CSS文件更小,因为它只生成你用到的工具类。
  • 它可以让你的CSS更一致,因为它遵循一套预设的规则和变量。
  • 它可以让你的CSS更灵活,因为它支持自定义工具类,变体,指令和图标
  • 它可以让你的CSS更易于维护,因为它避免了样式冲突和重复代码

官网:https://unocss.dev/integrations/vite

安装Unocss

npm install -D unocss

vite配置

  1. 再src同级目录下创建unocss.config.tsx,写入:
import { defineConfig, presetAttributify, presetUno } from "unocss";
export default defineConfig({
  presets: [
    presetAttributify(),
    presetUno(),
  ],
});

2.配置vite.config.tsx

import { defineConfig } from 'vite'
import UnoCss from "unocss/vite"
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), UnoCss()],
})
  1. main.tsx中引入virtual:uno.css
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import "virtual:uno.css"

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

搜索其他的样式使⽤

https://www.tailwindcss.cn/

安装自动引入插件

说明

unplugin-auto-import 这个插件是为了解决在开发中的导入问题,比如经常不清楚相对路径的问题,这个插件就是解决这个问题,这个插件会在根目录生成一个auto-import.d.ts,这个文件会将所有的插件导入到global中,这样在使用的时候直接就可以使用了。

安装

npm i -D unplugin-auto-import

配置文件vite.config.ts

import { defineConfig } from 'vite'
import UnoCss from "unocss/vite"
import react from '@vitejs/plugin-react'
import AutoImport from "unplugin-auto-import/vite";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    UnoCss(),
    AutoImport({
      dts: 'src/types/auto-imports.d.ts',
      imports: ['react'],
      dirs: ['./src/hooks']
    }),
  ],
})

结果:
react项目初始化

开始开发

首页顶部开发准备工作

  1. 引入首页重置的css
html
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
a {
  text-decoration: none;
  color: inherit;    
}
ul {
  list-style: none;
}
button {
  border: none;
  background: none;
  cursor: pointer;
}
.ant-carousel .index-arrow-left,
.ant-carousel .index-arrow-left:hover,
.ant-carousel .index-arrow-left:focus {
  font-size: 30px;
  left: 20px;
  z-index: 2;
  color: #4e4d53;
}
.ant-carousel .index-arrow-right,
.ant-carousel .index-arrow-right:hover,
.ant-carousel .index-arrow-right:focus {
  font-size: 30px;
  right: 30px;
  z-index: 2;
  color: #4e4d53;
}

main.tsx进行引入

	import "../src/assets/react.css"
  1. 创建commponents文件夹,再创建heard.tsx组件
    react项目实战演练

海报图

海报图链接:https://file.xdclass.net/video/2023/banner/618/QD.gif
设置宽度100%,超出隐藏
在这里插入图片描述

高阶函数组件渲染导航条

  1. 使用高阶组件,来循环遍历产生头部tab导航,传入参数,title,href,以及chilren组件。
import { Input } from "antd"
	import { DownOutlined } from "@ant-design/icons";
	//tab每一项的接口定义 高阶函数
	interface HeaderItemProps {
	  href: string;
	  title: string;
	  children: React.ReactNode
	}
	// 高阶组件(组件作为参数,返回组件)
	const HeaderItem = (props: HeaderItemProps) => {
	  return (
	    <a href={props.href} className="c-#4f55d hover:c-#f38e48">
	      {props.children ?? props.title}
	    </a>
	  )
	}
	// 头部导航组件
	const Heard = () => {
	  // 每项tab的配置
	  const tabList = [
	    { title: "首页", href: "#" },
	    { title: "课程中心", href: "#" },
	    {
	      title: "超级会员", href: "#", children: (
	        <div className="flex items-center justify-center">
	          <img src="https://front.cdn.xdclass.net/images/vip_icon.webp" className="w-22px h-20px" />
	          <span className="ml-4px">超级会员</span>
	        </div>
	      )
	    },
	    { title: "工具", href: "#" },
	    {
	      title: "自学路线", href: "#", children: (
	        <div>
	          <span>自学路线</span>
	          <DownOutlined className="ml-4px"></DownOutlined>
	        </div>
	      )
	    },
	    {
	      title: "一对一辅导", href: "#", children: (
	        <div>
	          <span>一对一辅导</span>
	          <DownOutlined className="ml-4px"></DownOutlined>
	        </div>
	      )
	    },
	    {
	      title: "", href: "#", children: (
	        <div>
	          <Input.Search placeholder="请输入搜索内容" className="w-220px"></Input.Search>
	        </div>
	      )
	    },
	    { title: "兑换码", href: "#" },
	    { title: "云服务器", href: "#" },
	  ]
	  return (
	    <div className="flex items-center gap-2">
	      {/* 官网图表 */}
	      <img src="https://front.cdn.xdclass.net/images/logo.webp" className="w-138px h-64px" alt="" />
	      {/* tab导航项 */}
	      <div className="flex items-center justify-between flex-1">
	        {
	          tabList.map((item, index) => (
	            <HeaderItem key={index} href={item.href} title={item.title} >
	              {
	                item?.children
	              }
	            </HeaderItem>
	          ))
	        }
	      </div>
	      {/* 注册登录 */}
	      <div className="flex items-center justify-center gap-4 children:cursor-pointer">
	        <span className="ml-8px">登录</span>
	        <span className="bg-#4d555d c-#fff h-30px leading-26px w-60px p-2px text-center" >注册</span>
	      </div>
	    </div>
	  )
	}
	export default Heard

顶部tab导航栏效果:

在这里插入图片描述

注册登录开发

输入账号和密码,注册成功后保存账号密码,保存在localStorage里面

完成效果图:react项目实战

安装React状态管理库 Zustand

作为React开发者,我们经常需要处理组件之间的状态管理。在大型应用程序中,这可能会变得相当复杂和繁琐。为了简化这个过程,许多状态管理库被开发出来,其中一个非常受欢迎的选择是Zustand。Zustand是一个简单易用的JavaScript库,它提供了一种简洁的方式来管理React应用程序的状态。
Zustand的设计理念是将状态管理的复杂性降到最低,同时提供了一个强大的工具集来处理状态。它采用了一个类似于React Hook的API,使得状态的定义和使用非常直观和简单。

npm install zustand
  1. 创建hooks/modal.ts,使用zustand进行状态管理
import { create } from "zustand";
// 弹窗状态定义窗口
interface ModalState{
  regVisible:boolean,
  switchRegVisible:()=>void
}
export const useModal = create<ModalState>((set)=>({
  // 注册弹窗状态
  regVisible:false,
  switchRegVisible:()=>set((state)=>({regVisible:!state.regVisible}))
}));
  1. 由于上面已经安装了自动引入插件,所以hooks不需要引入,直接使用
    Header.tsx使用
  2. 创建Register.jsx并Header.jsx中引入Register.jsx
 const {switchRegVisible} = useModal()
  1. 直接使用switchRegVisible修改注册弹窗状态方法
<span className="bg-#4d555d c-#fff h-30px leading-26px w-60px p-2px text-center" onClick={switchRegVisible}>注册</span>
  1. 创建Register.jsx并引入
import { Modal, Form, Input, Button, message } from "antd";
export function Register() {
  // 账号
  const [account, setAccount] = useState("");
  // 密码
  const [password, setPassword] = useState("");
  // 确认密码
  const [rePassword, setRePassword] = useState("");
  // 全局公共个⼈状态
  const { register, users } = useUser();
  // 全局公共注册弹窗状态
  const { regVisible, switchRegVisible } = useModal();
  // 注册提交按钮
  function handleFinish() {
    // 密码验证;
    if (password !== rePassword) {
      message.warning("两次密码不⼀致");
      return;
    } else {
      // 账号验证
      if (users.some((user) => user.account === account)) {
        message.warning("该账号已存在");
      } else {
        // 注册
        register(account, password);
        // 关闭注册弹窗
        switchRegVisible();
        message.success("注册成功");
      }
    }
  }
  return (
    <Modal
      width="400px"
      open={regVisible}
      footer={null}
      className="relative"
      onCancel={switchRegVisible}
    >
      <h1 className="text-center c-#404040 text-22px font-normal my-8">
        密码登录
      </h1>
      <div className="pb-44px flex items-center justify-center w-full">
        <Form
          name="basic"
          style={{ width: "300px" }}
          initialValues={{ remember: true }}
          autoComplete="off"
          onFinish={handleFinish}
        >
          {/* 账号 */}
          <Form.Item name="account">
            <Input
              placeholder="请输⼊账号"
              value={account}
              onChange={(e) => setAccount(e.target.value)}
            />
          </Form.Item>
          {/* 密码 */}
          <Form.Item name="password">
            <Input.Password
              placeholder="请输⼊密码"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
            />
          </Form.Item>
          {/* 确认密码 */}
          <Form.Item name="re-password">
            <Input.Password
              placeholder="请再次输⼊密码"
              value={rePassword}
              onChange={(e) => setRePassword(e.target.value)}
            />
          </Form.Item>
          {/* 注册 */}
          <Form.Item>
            <Button
              type="primary"
              htmlType="submit"
              className="flex w-full items-center justify-center bg-#444b52 textwhite rounded-full"
            >
              <span>⽴即注册</span>
            </Button>
          </Form.Item>
        </Form>
      </div>
      {/* 跳转登录 */}
      <div className="absolute w-full h-44px bottom-0 left-0 bg-
[rgba(77,85,93,0.1)] flex items-center justify-center">
        <span>已有账号?</span>
        <span className="text-blue-400 cursor-pointer">⽴即登录</span>
      </div>
    </Modal>
  );
}
import Register from "./Register";
  1. 创建hooks/user.ts,使用zustand进行状态管理
import { create } from "zustand";

// 接口定义
interface UserState {
  users: {
    account: string;
    password: string;
  }[];
  register: (account: string, password: string) => void;
}
export const useUser = create<UserState>((set) => ({
  // 用户信息状态
  users: localStorage.getItem("xdclass_react_users")
    ? JSON.parse(localStorage.getItem("xdclass_react_users") || "[]")
    : [],
  // 注册更新用户信息
  register: (account, password) =>
    set((state) => {
      // 复制原数据
      const users = [...state.users];
      users.push({
        account,
        password,
      });
      // 数据缓存
      localStorage.setItem("xdclass_react_users", JSON.stringify(users));
      return {
        users,
      };
    }),
}));

完成效果:
在这里插入图片描述
未完待续~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MinIO实现数据迁移(mc)

运行两个版本的minio version: 2.3 services: # 新版本 minio2023: image: minio/minio:RELEASE.2022-06-20T23-13-45Z.fips container_name: minio2023 restart: always environment: - MINIO_ACCESS_KEYminioadmin - MINIO_SECRET_KEYminioadmin - MINIO_ROOT_USERminioadm…

为什么要使用动态代理IP?数据采集使用动态代理有哪些优势?

随着互联网的普及&#xff0c;数据采集已经成为企业、营销人员和数据分析师的重要工作之一。然而&#xff0c;在采集数据的过程中&#xff0c;经常会遇到一些问题&#xff0c;如IP被封禁、访问受限等。为了解决这些问题&#xff0c;动态代理IP应运而生。那么&#xff0c;为什么…

TP-LINK联洲面试题

文章目录 1.说一下微服务架构?2.微服务优缺点3.负载均衡的实现算法4.Redis集群部署方式?5.MySQL主从复制?5.1 配置流程5.2 优缺点分析6.口头手撕快排7.队列实现栈和栈实现队列7.1 队列实现栈7.2 栈实现队列8.进程有几种状态?9.Spring Boot Actuator?10.外键、主键和索引?…

数字化转型具体包含哪些内容?

数字化转型是一个广泛且多方面的过程&#xff0c;涉及将数字技术集成到组织或企业的各个方面&#xff0c;从根本上改变其运营和交付价值的方式。它包含广泛的活动、战略和举措&#xff0c;这些活动、战略和举措可能会根据组织的具体目标和需求而有所不同。以下是数字化转型的一…

谁家分析数据还要开发啊,不都一键得报表吗?

点击导入数据&#xff0c;再回来BI系统已经把近百张数据分析报表放在眼前了&#xff0c;每月都要计算分析的指标有了&#xff0c;领导要的数据分析有了&#xff0c;自己要的业绩分析也有了&#xff0c;甚至自己没想到的一些分析主题&#xff0c;它也贴心地做好了。有这样一套BI…

微信抽奖活动怎么做

微信抽奖活动&#xff1a;打破传统&#xff0c;创新互动&#xff0c;带给你超乎想象的惊喜体验&#xff01; 随着互联网的飞速发展&#xff0c;人们越来越热衷于参与各种线上活动。而微信&#xff0c;作为中国最大的社交平台之一&#xff0c;自然成为了各种活动的聚集地。今天…

什么是CDN?什么是安全加速CDN?有什么优势?

安全加速CDN(Content Delivery Network)是一种网络架构&#xff0c;它通过在全球范围内部署服务器并缓存静态和动态内容来提供更快的Web页面加载和更好的用户体验。安全加速CDN可以保护网站免受DDoS攻击、恶意软件和其他安全威胁&#xff0c;从而提高网站的可用性和稳定性。它通…

Python武器库开发-flask篇之Get与Post(二十五)

flask篇之Get与Post(二十五) 在Flask中通过request对象请求相关的数据,在正常的网页请求的过程中&#xff0c;有两种请求的方式&#xff0c;Get和Post Get请求 我们现在来看看在Flask中是如何以Get方式得到我们想要的值的&#xff0c;通过request.args可以获取Get请求中的所…

QT 使用mysql

版本&#xff1a;ubuntu&#xff1a;20.04.1 mysql&#xff1a; 8.0.35 QT &#xff1a;5.12.8 1.安装mysql sudo apt install mysql-server 下载完后查看mysql状态 sudo service mysql status 如下图active&#xff08;running&#xff09;则下载成功&#xff0c;运行中…

蓝牙运动耳机哪个好?适合运动时戴的蓝牙耳机有哪些?

​在各式各样的耳机当中&#xff0c;运动耳机可以说是使用场景最广的一类了。毕竟运动耳机对于某些方面性能要求会比非运动耳机要高很多&#xff0c;就比如户外运动、健身、骑行等方面。面对这么多运动耳机&#xff0c;哪款更值得入手&#xff1f;今天就来给大家推荐几款很不错…

渔业可视化渔业数字孪生

渔业可视化&渔业数字孪生 帮威客打造的渔业可视化&渔业数字孪生&#xff0c;适用于室内塘口养殖、室外塘口养殖、室外大水面养殖等场景&#xff0c;可运用于鱼类、虾类、贝类、蟹类、鳖类等水产作物养殖过程&#xff0c;旨在助力水产养殖日常管理的数字化、智能化、自动…

Windows 小狼毫 如何在安装后指定用户配置文件文件夹

Windows 小狼毫 如何在安装后指定用户配置文件文件夹 打开小狼毫的安装目录&#xff0c;双击目录中的 WeaselSetup.exe 就会弹出截图中的那个窗口&#xff0c;然后指定你的用户文件夹目录就可以了

网络协议头分析及抓包三次挥手四次握手

数据的封装与传递过程 思考&#xff1a; 应用层调用send后&#xff0c;是如何把数据发送到另一台机器的某个进程的。接收的设备收到数据包后&#xff0c;如何处理给应用层&#xff1f; MTU &#xff1a; Maximum Transmit Unit 最大传输单元 物理接口&#xff08;数据链路层&am…

数组按照传入的字段排序

排序方法 mounted () {const oldArr [{name: a123,code: a,snapshotId: ff8081818bd09640018bd09640860000,showList: null,orderList: null,sortOrder: null,sortNumber: 2,isSelected: false}, {name: 端口流量,code: throughput,snapshotId: 37,showList: null,orderList:…

Linux基础命令(2)

现在class03下面有这些 用ls -R看到test里面也是有东西的&#xff0c;也就是test目录文件非空 那么现在在03下面mkdir建一个空的目录文件tes&#xff0c;刚建好里面还什么都没有放 那么想要删除操作的话——要用什么命令 1.rmdir&#xff1a;用来删除空的目录文件的命令 删除刚…

【嵌入式开发学习】__扒一扒单片机串口IAP原理

一、什么是IAP&#xff1f; IAP 是 In Application Programming 的首字母缩写&#xff0c;IAP是用户自己的程序在运行过程中对 User Flash 的部分区域进行烧写&#xff0c;目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。 在重新编程过程…

HCIA-综合实验(三)

综合实验&#xff08;三&#xff09; 1 实验拓扑2 IP 规划3 实验需求一、福州思博网络规划如下&#xff1a;二、上海思博网络规划如下&#xff1a;三、福州思博与上海思博网络互联四、网络优化 4 配置思路4.1 福州思博配置在 SW1、SW2、SW3 上配置交换网络SW1、SW2、SW3 运行 S…

Matlab通信仿真系列——变量、矩阵及其运算

微信公众号上线&#xff0c;搜索公众号小灰灰的FPGA,关注可获取相关源码&#xff0c;定期更新有关FPGA的项目以及开源项目源码&#xff0c;包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等 本节目录 一、变量 (1)变量的赋值…

DNS服务器的访问日志

DNS服务器的访问日志的目录位置取决于具体使用的DNS服务器软件和操作系统。一般来说&#xff0c;常见的DNS服务器软件如Bind、PowerDNS、Unbound等会有各自的默认日志目录&#xff0c;例如&#xff1a; Bind&#xff1a;默认存储在/var/log/named/目录下。PowerDNS&#xff1a…

AI创作系统ChatGPT网站源码/支持DALL-E3文生图/支持最新GPT-4-Turbo模型+Prompt应用

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…