【React】极客园案例实践-项目搭建和登录模块

极客园

1、项目搭建

1-1 创建项目

基于CRA

CRA是一个底层基于webpack快速创建React项目的脚手架工具

bash 复制代码
# 使用npx创建项目
npx create-react-app react-jike

# 进入到项
cd react-jike

# 启动项目
npm start

基于vite

Vite官方中文文档

bash 复制代码
npm create vite@latest react-jike -- --template react

# 进入到项
cd react-jike

# 安装依赖
nmp install

# 启动项目
npm run dev

1-2 调整项目目录结构

bash 复制代码
-src
  -apis           项目接口函数
  -assets         项目资源文件,比如,图片等
  -components     通用组件
  -pages          页面组件
  -router         路由
  -store          集中状态管理
  -utils          工具,比如,token、axios 的封装等
  -App.js         根组件
  -index.css      全局样式
  -index.js       项目入口

src/main.jsx

jsx 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.scss'
import './App.js'

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

src/App.jsx

jsx 复制代码
const App = () => {
  return <div>this is app</div>
}

export default App

1-3 使用scss预处理器

SASS 是一种预编译的 CSS,支持一些比较高级的语法,可以提高编写样式的效率,CRA接入scss非常简单只需要我们装一个sass工具

实现步骤

  1. 安装解析 sass 的包:npm i sass -D
  2. 创建全局样式文件:index.scss
css 复制代码
body {
  margin: 0;
  div {
    color: blue;
  }
}

1-4 组件库antd使用

极客园项目是一个传统的PC管理后台,有现成的组件库可以使用,帮助我们提升开发效率,其中使用最广的就是antD

Ant Design of React - Ant Design

实现步骤

  1. 安装 antd 组件库:npm i antd
  2. 导入 Button 组件
  3. 在 Login 页面渲染 Button 组件进行测试

测试Button
pages/Login/index.jsx

jsx 复制代码
import { Button } from 'antd'

const Login = () => {
  return <div>this is login<Button type='primary'>test</Button></div>
}
export default Login

1-5 配置基础路由

React Router中文文档

单页应用需要对应的路由支持,我们使用 react-router-dom 最新版本

实现步骤

  1. 安装路由包 npm i react-router-dom
  2. 准备 LayoutLogin俩个基础组件
  3. 配置路由

代码实现
pages/Layout/index.jsx

jsx 复制代码
const Layout = () => {
  return <div>this is layout</div>
}
export default Layout

pages/Login/index.jsx

jsx 复制代码
const Login = () => {
  return <div>this is login</div>
}
export default Login

router/index.jsx

jsx 复制代码
import { createBrowserRouter } from 'react-router-dom'

import Login from '../pages/Login'
import Layout from '../pages/Layout'

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
  },
  {
    path: '/login',
    element: <Login />,
  },
])

export default router

main.jsx

jsx 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.scss'
import router from './router'
import { RouterProvider } from 'react-router-dom'

ReactDOM.createRoot(document.getElementById('root')).render(
    <RouterProvider router={router} />
)

1-6 配置别名路径

项目背景:在业务开发过程中文件夹的嵌套层级可能会比较深,通过传统的路径选择会比较麻烦也容易出错,设置路径别名可以简化这个过程

路径编译配置

CRA创建的项目
  1. 安装 craco 工具包
  2. 增加 craco.config.js 配置文件
  3. 修改 scripts 命令
  4. 测试是否生效
bash 复制代码
npm i @craco/craco -D
javascript 复制代码
const path = require('path')

module.exports = {
  // webpack 配置
  webpack: {
    // 配置别名
    alias: {
      // 约定:使用 @ 表示 src 文件所在路径
      '@': path.resolve(__dirname, 'src')
    }
  }
}
json 复制代码
"scripts": {
  "start": "craco start",
  "build": "craco build",
  "test": "craco test",
  "eject": "react-scripts eject"
}
javascript 复制代码
import { createBrowserRouter } from 'react-router-dom'

import Login from '@/pages/Login'
import Layout from '@/pages/Layout'

const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
  },
  {
    path: '/login',
    element: <Login />,
  },
])

export default router
vite创建的项目

Vite 本身内置了路径别名(别名解析) 的配置能力,无需额外安装类似 craco 的插件,直接在 vite.config.js/ts 中通过 resolve.alias 配置即可实现路径解析,这是 Vite 原生支持的核心特性,比 CRA + craco 更简洁。

vite.config.js

jsx 复制代码
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import * as path from 'path';
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  resolve: {
    // 路径别名配置
    alias: {
      // 配置 @ 指向 src 目录
      '@': path.resolve(__dirname, 'src'),
    },
  },
})

VsCode提示配置

vite和CRA创建都需要

实现步骤

  1. 在项目根目录创建 jsconfig.json 配置文件
  2. 在配置文件中添加以下配置

代码实现

json 复制代码
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

说明:VSCode会自动读取jsconfig.json 中的配置,让vscode知道@就是src目录

使用gitee管理项目

实现步骤

  1. 在gitee上初始化一个空项目仓库
  2. 把远程仓库和本地仓库关联
  3. 提交代码到远程仓库


提交代码-01项目搭建

2、登录模块

2-1 基本结构搭建

实现步骤

  1. Login/index.js 中创建登录页面基本结构
  2. 在 Login 目录中创建 index.scss 文件,指定组件样式
  3. logo.pnglogin.png 拷贝到 assets 目录中

代码实现
pages/Login/index.js

jsx 复制代码
import './index.scss'
import { Card, Form, Input, Button } from 'antd'
import logo from '@/assets/logo.png'

const Login = () => {
  return (
    <div className="login">
      <Card className="login-container">
        <img className="login-logo" src={logo} alt="" />
        {/* 登录表单 */}
        <Form>
          <Form.Item>
            <Input size="large" placeholder="请输入手机号" />
          </Form.Item>
          <Form.Item>
            <Input size="large" placeholder="请输入验证码" />
          </Form.Item>
          <Form.Item>
            <Button type="primary" htmlType="submit" size="large" block>
              登录
            </Button>
          </Form.Item>
        </Form>
      </Card>
    </div>
  )
}

export default Login

pages/Login/index.scss

css 复制代码
.login {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  background: center/cover url('@/assets/login.png');

  .login-logo {
    width: 200px;
    height: 60px;
    display: block;
    margin: 0 auto 20px;
  }

  .login-container {
    width: 440px;
    height: 360px;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    box-shadow: 0 0 50px rgb(0 0 0 / 10%);
  }

  .login-checkbox-label {
    color: #1890ff;
  }
}

2-2 表单校验实现

表单校验可以在提交登录之前校验用户的输入是否符合预期,如果不符合就阻止提交, 显示错误信息

1-参考官网实现基础Demo FormItem绑定name/FormItem绑定rules

2-按照业务定制化修改 增加失焦时校验/手机号为有效格式

实现步骤

  1. 为 Form 组件添加 validateTrigger 属性,指定校验触发时机的集合
  2. 为 Form.Item 组件添加 name 属性
  3. 为 Form.Item 组件添加 rules 属性,用来添加表单校验规则对象


validateTrigger="onBlur"实现失焦时校验

代码实现
page/Login/index.js

2-3 获取登录表单数据

当用户输入了正确的表单内容,点击确认按钮时需要收集到用户当前输入的内容,用来提交接口请求

解决方案:给Form组件绑定onFinish回调函数,通过回调函数的参数获取用户输入的内容

实现步骤

  1. 为 Form 组件添加 onFinish 属性,该事件会在点击登录按钮时触发
  2. 创建 onFinish 函数,通过函数参数 values 拿到表单值
  3. Form 组件添加 initialValues 属性,来初始化表单值

代码实现
pages/Login/index.js

测试

提交代码-02登录表单校验和数据收集

2-4 封装request工具模块

业务背景: 前端需要和后端拉取接口数据,axios是使用最广的工具插件,针对于项目中的使用,我们需要做一些简单的封装

实现步骤

  1. 安装 axios 到项目
  2. 创建 utils/request.js 文件
  3. 创建 axios 实例,配置 baseURL,请求拦截器,响应拦截器
  4. 在 utils/index.js 中,统一导出request
bash 复制代码
npm i axios

代码实现
utils/request.jsx

jsx 复制代码
// axios的封装处理

const { default: axios } = require("axios");

// 1.根域名配置
// 2.超时时间
// 3.请求拦截器 / 响应拦截器

const request = axios.create({
  baseURL: 'http://geek.itheima.net/v1_0',
  timeout: 5000
})

// 添加请求拦截器
// 在请求发送之前 做拦截 插入一些自定义的配置 [参数的处理]
request.interceptors.request.use((config) => {
  return config
}, (error) => {
  return Promise.reject(error)
})

// 添加响应拦截器
// 在响应返回客户端之前 做拦截 重点处理返回的数据
request.interceptors.response.use((response) => {
  // 2xx 范围内的状态码都会触发该函数。
  // 对响应数据做点什么
  return response.data
}, (error) => {
  // 超出 2xx 范围的状态码都会触发该函数。
  // 对响应错误做点什么
  return Promise.reject(error)
})

export { request }

utils/index.jsx

bash 复制代码
// 统一中转工具模块函数
import { request } from "./request"
export {
  request
}

Axios

提交-03登录-axios封装处理

2-5 使用Redux管理token

安装Redux相关工具包

bash 复制代码
npm i react-redux @reduxjs/toolkit

配置Redux

代码实现
user.jsx

jsx 复制代码
// 用户相关的状态管理
import { createSlice } from "@reduxjs/toolkit"
const useStore = createSlice({
  name: 'user',
  // 数据状态
  initialState: {
    token: ''
  },
  // 同步修改方法
  reducers: {
    setToken(state, action) {
      state.token = action.payload
    }
  }
})

// 解构出actionCreater
const { setToken } = useStore.actions

// 获取reducer函数

const userReducer = useStore.reducer

export { setToken }

export default userReducer

index.jsx

jsx 复制代码
// 组合redux子模块 导出store实例
import { configureStore } from "@reduxjs/toolkit"
import userReducer from "./modules/user"

const store = configureStore({
  reducer: {
    user: userReducer
  }
})

export default store

main.jsx

jsx 复制代码
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.scss'
import router from './router'
import { RouterProvider } from 'react-router-dom'
import { Provider } from 'react-redux'
import store from './store'

ReactDOM.createRoot(document.getElementById('root')).render(
  <Provider store={store}>
    <RouterProvider router={router} />
  </Provider>
)


黑马前端接口文档

在接口文章找到注册登录的post地址复制,编写异步方法

在组件中触发异步方法

测试,正确的11位手机号,注意验证码是246810,输入别的会发生错误

2-6 实现登录逻辑

业务逻辑:

  1. 跳转到首页
  2. 提示用户登录成功

使用async/await

async:给函数 "打标签",标记这是异步函数

await:"等待" Promise 完成,提取最终结果
代码实现

提交-04使用redux维护数据

2-7 token持久化

业务背景: Token数据具有一定的时效时间,通常在几个小时,有效时间内无需重新获取,而基于Redux的存储方式又是基于内存的,刷新就会丢失,为了保持持久化,我们需要单独做处理

原因:Redux是基于浏览器内存的存储方式,刷新时状态会恢复初始值

实现持久化逻辑

代码实现

测试,刷新浏览器,通过Redux调试工具查看token数据

提交-05token持久化

封装token的存取方法

对于Token的各类操作在项目多个模块中都有用到,为了共享复用可以封装成工具函数

代码实现
utils/token.jsx

utils/index.jsx

修改store/modules/user.jsx

提交-06封装token工具和方法

2-8 请求拦截器注入token

业务背景: Token作为用户的数据标识,在接口层面起到了接口权限控制的作用,也就是说后端有很多接口都需要通过查看当前请求头信息中是否含有token数据,来决定是否正常返回数据(接口权限)


拼接方式:config.headers.Authorization = `Bearer ${token}`

config.headers.Authorization:axios 提供的 "请求头字段"

`Bearer ${token}`:后端要求的 "Token 格式",两者之间必须加一个空格

注意:这个拼接方式一定要写对,不然就会请求失败
代码实现

测试

提交-07token的注入

2-9 路由鉴权实现

业务背景:封装 AuthRoute 路由鉴权高阶组件,实现未登录拦截,并跳转到登录页面(路由权限)

实现思路:判断本地是否有token,如果有,就返回子组件,否则就重定向到登录Login

根据Token的有无控制当前路由是否可以跳转就是路由的权限控制

高阶组件:接收组件作为参数,返回新组件的函数(不是组件,是 "造组件的函数")。

实现步骤

  1. 在 components 目录中,创建 AuthRoute/index.jsx 文件
  2. 登录时,直接渲染相应页面组件
  3. 未登录时,重定向到登录页面
  4. 将需要鉴权的页面路由配置,替换为 AuthRoute 组件渲染

代码实现
components/AuthRoute.jsx

Router/index.jsx

提交08-token控制路由权限

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax