# react-antd-h5 **Repository Path**: 674074365/react-antd-h5 ## Basic Information - **Project Name**: react-antd-h5 - **Description**: react+antd+vite移动端h5项目 - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 30 - **Forks**: 8 - **Created**: 2023-11-28 - **Last Updated**: 2026-05-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: React, vite, antd-mobile ## README # React Antd Mobile H5

React Vite Ant Design Mobile Redux Node.js License

基于 **React 19 + Vite 8 (SWC) + Ant Design Mobile 5 + Redux** 的移动端 H5 电商模板项目,采用纯 JavaScript (JSX) 开发,集成路由缓存、全局自动导入、模块化 Redux、国际化、常量管理、请求封装等企业级开发方案。 ## 特性 - **React 19** + **Vite 8 (SWC)** — 极速开发体验,闪电般的 HMR - **Ant Design Mobile 5** — 高质量移动端 UI 组件库 - **路由缓存** — 基于 `react-activation` + 自定义 `useNavigate` 实现页面级 KeepAlive 缓存 - **全局自动导入** — `unplugin-auto-import` 实现 React Router / i18next / 自定义 Hooks 零导入使用 - **模块化 Redux** — 约定式目录结构,`import.meta.glob` 自动加载,支持 Redux DevTools - **常量管理** — 模块化常量定义,`import.meta.glob` 自动加载,`$globalConstant` 统一访问 - **请求封装** — 基于 Axios 的统一请求层,支持 GET / POST / PUT / DELETE / JSONP / FormData - **Mock 数据** — 内置 Mock 模式,支持全局 link/mock 切换,覆盖全部接口的本地模拟数据 - **国际化** — `i18next` + `react-i18next`,支持远程接口动态覆盖本地语言包 - **事件总线** — 基于 `mitt` 的全局事件通信,`$globalEventBus` 自动导入 - **Vite 插件模块化** — 自定义插件按文件自动加载(copy / zip / legacy / progress) - **ESLint 9 + Prettier** — Flat Config 方案,0 errors 0 warnings - **移动端适配** — `postcss-pxtorem` + `amfe-flexible` 自动 rem 转换 - **Less + CSS Modules** — 局部样式隔离 + `:global` 覆盖 UI 库样式 ## 技术栈 | 类别 | 技术 | 版本 | |------|------|------| | 框架 | React | ^19.2.6 | | 构建工具 | Vite (SWC) | ^8.0.11 | | UI 组件库 | Ant Design Mobile | ^5.42.3 | | 状态管理 | Redux + react-redux + redux-thunk + redux-promise | ^5.0.1 | | 路由 | react-router-dom (HashRouter) | ^7.15.0 | | 路由缓存 | react-activation | ^0.13.4 | | 不可变状态 | immer | ^11.1.8 | | 请求 | axios | ^1.16.0 | | 国际化 | i18next + react-i18next | ^26.0.10 / ^17.0.7 | | 事件总线 | mitt | ^3.0.1 | | 样式 | Less + postcss-pxtorem | ^4.6.4 / ^6.1.0 | | 代码规范 | ESLint 9 (flat config) + Prettier | ^9.39.4 / ^3.8.3 | | 自动导入 | unplugin-auto-import | ^21.0.0 | ## 快速开始 ### 环境要求 - Node.js >= 18.0.0 - npm >= 9.0.0 ### 安装依赖 ```bash npm install ``` ### 开发 ```bash npm run dev ``` 启动后访问 `http://localhost:3301` ### 构建 ```bash # 测试环境构建 npm run build:dev # 生产环境构建(构建完成后自动生成 dist.zip) npm run build:pro ``` ### 代码检查与格式化 ```bash # ESLint 检查(0 errors 0 warnings) npm run lint # Prettier 格式化 npm run format # Prettier 检查 npm run format:check ``` ### 文档站点 ```bash # 启动文档开发服务器 npm run docs:dev # 构建文档 npm run docs:build ``` ## 项目预览 | 登录 | 首页 | 分类 | 购物车 | 我的 | |------|------|------|--------|------| | ![登录](https://gitee.com/674074365/react-antd-h5/raw/master/preview/%E7%99%BB%E5%BD%95.jpeg) | ![首页](https://gitee.com/674074365/react-antd-h5/raw/master/preview/%E9%A6%96%E9%A1%B5.jpeg) | ![分类](https://gitee.com/674074365/react-antd-h5/raw/master/preview/%E5%88%86%E7%B1%BB.jpeg) | ![购物车](https://gitee.com/674074365/react-antd-h5/raw/master/preview/%E8%B4%AD%E7%89%A9%E8%BD%A6.jpeg) | ![我的](https://gitee.com/674074365/react-antd-h5/raw/master/preview/%E6%88%91%E7%9A%84.jpeg) | ## 目录结构 ``` react-antd-h5/ ├── src/ │ ├── api/ # API 接口定义(预留) │ ├── assets/ # 静态资源(图片、SVG) │ ├── components/ # 公共组件 │ │ ├── footer-nav/ # 底部导航栏 │ │ ├── header-nav/ # 顶部导航栏 │ │ ├── refresh-scroll/ # 下拉刷新组件 │ │ └── wc-swiper/ # 轮播组件 │ ├── constant/ # 常量定义(模块化,按文件自动加载) │ │ ├── eventBus.js # 事件总线常量 │ │ └── resultCode.js # 接口响应码常量 │ ├── hooks/ # 全局自动导入 Hooks │ │ ├── useCommon.js # 公共函数(初始化数据加载、i18n 远程覆盖) │ │ ├── useConstant.js # $globalConstant - 常量模块自动加载 │ │ ├── useCustomNavigate.js # 自定义 useNavigate(替代原生,支持缓存刷新) │ │ ├── useEventBus.js # $globalEventBus - mitt 事件总线 │ │ ├── useFetch.js # $globalRequest / $globalRequestUrl - 请求封装 │ │ ├── useInitialize.jsx # $globalReady - 应用入口组件 │ │ ├── useKeepRouter.jsx # $globalLazy / $globalKeepRouter - 路由缓存 │ │ ├── useLoadRouter.jsx # $globalRouter - 路由自动加载 │ │ ├── usePrompt.jsx # $globalGuard - 路由守卫 │ │ ├── useRedux.js # $globalRedux / $globalReduxAction - Redux Store │ │ └── useService.js # $globalServicer - 请求模块自动加载 │ ├── locales/ # 国际化语言包 │ │ ├── index.js # i18next 配置入口 │ │ ├── ZH-CN/ # 中文语言包 │ │ │ └── common.json │ │ └── US-EN/ # 英文语言包 │ │ └── common.json │ ├── redux/ # Redux 状态管理(模块化) │ │ ├── common/ # 公共模块 │ │ │ ├── reduxAction.js │ │ │ ├── reduxReducer.js │ │ │ └── reduxType.js │ │ └── login/ # 登录模块 │ │ ├── reduxAction.js │ │ ├── reduxReducer.js │ │ └── reduxType.js │ ├── router/ # 路由配置(按页面拆分,自动加载) │ │ ├── common.jsx # 公共路由(登录、404) │ │ ├── home.jsx # 首页路由 │ │ ├── classify.jsx # 分类路由 │ │ ├── shop.jsx # 购物车路由 │ │ ├── detail.jsx # 详情路由 │ │ └── my.jsx # 我的路由 │ ├── service/ # 请求模块(模块化,按文件自动加载) │ │ ├── common.js # 公共接口(购物车数量、商品详情、语言包) │ │ ├── home.js # 首页接口(轮播图、精品、推荐) │ │ ├── Classify.js # 分类接口 │ │ ├── ShopCard.js # 购物车接口 │ │ └── My.js # 个人中心接口 │ ├── styles/ # 全局样式 │ │ └── common.less │ ├── views/ # 页面组件 │ │ ├── 404.jsx │ │ ├── login/ │ │ ├── home/ │ │ ├── classify/ │ │ ├── detail/ │ │ ├── shop/ │ │ ├── my/ │ │ └── components/ # 页面级私有组件 │ └── main.jsx # 应用入口 ├── vite-config/ # Vite 配置(模块化) │ ├── index.js # 基础配置 + 插件自动加载 │ └── plugins/ # Vite 插件(按文件自动加载) │ ├── unplugin-auto-import.js # 全局自动导入配置 │ ├── vite-plugin-copy.js # 构建产物复制 │ ├── vite-plugin-legacy.js # 低版本浏览器兼容 │ ├── vite-plugin-progress.js # 构建进度条 │ └── vite-plugin-zip.js # 构建产物打包 ├── vite-env/ # 环境变量配置 │ ├── .env # 本地环境 │ ├── .env.dev # 测试环境 │ └── .env.prod # 生产环境 ├── mock/ # Mock 数据(按模块拆分,URL 自动匹配) │ ├── index.js # 入口聚合 + URL 匹配 │ ├── auth.js # 登录接口 │ ├── common.js # 公共接口(购物车数量、语言包、路由) │ ├── home.js # 首页接口(轮播图、精品、推荐) │ ├── classify.js # 分类接口 │ ├── shop.js # 购物车接口 │ ├── address.js # 地址接口 │ └── goods.js # 商品详情接口 ├── docs/ # VitePress 文档站点 ├── eslint.config.js # ESLint 9 flat config ├── .prettierrc # Prettier 配置 ├── vite.config.js # Vite 入口配置 ├── index.html # HTML 模板 └── package.json ``` ## 核心功能 ### 路由缓存 基于 `react-activation` 实现页面级 KeepAlive 缓存,通过路由 `meta` 配置控制缓存策略,支持两种缓存模式: | 缓存模式 | 字段 | 说明 | 适用场景 | |----------|------|------|----------| | 常驻缓存 | `isAlwaysKeepAlive: true` | 页面始终保持在缓存中,永不销毁 | Tab 主页面(首页、分类、购物车、我的) | | 按需缓存 | `isKeepAlive: true` | 需要缓存但可能被淘汰的页面 | 详情页等非 Tab 页面 | ```jsx // src/router/home.jsx — Tab 主页面使用 isAlwaysKeepAlive import React from "react"; const routers = [ { path: "/home", element: $globalLazy(React.lazy(() => import("@/views/home/index"))), meta: { title: "首页", isAlwaysKeepAlive: true, // 常驻缓存,Tab 切换时保持状态 }, }, ]; export default $globalKeepRouter(routers); ``` ```jsx // src/router/detail.jsx — 非Tab 页面使用 isKeepAlive const routers = [ { path: "/detail", element: $globalLazy(React.lazy(() => import("@/views/detail/index"))), meta: { title: "详情", isKeepAlive: true, // 按需缓存 }, }, ]; ``` ```jsx // 页面中使用自定义 navigate(自动处理缓存刷新) const navigate = useNavigate(); navigate("/detail"); // 跳转到详情页 ``` > 跳转缓存页面时自动执行 `refreshScope`,返回时保持之前的状态。`$globalKeepRouter` 和自定义 `useNavigate` 内部同时识别 `isKeepAlive` 和 `isAlwaysKeepAlive` 两种配置。 ### 全局自动导入 通过 `unplugin-auto-import` 配置,以下 API 无需手动 import 即可直接使用: | 全局变量 | 来源 | 说明 | |----------|------|------| | `$globalReady` | useInitialize | 应用入口组件 | | `$globalRouter` | useLoadRouter | 路由自动加载 | | `$globalLazy` | useKeepRouter | 路由懒加载包装 | | `$globalKeepRouter` | useKeepRouter | 路由缓存配置 | | `$globalGuard` | usePrompt | 路由守卫 | | `$globalServicer` | useService | 请求模块自动加载 | | `$globalRequestUrl` | useFetch | 请求 URL 拼接 | | `$globalRequest` | useFetch | 统一请求方法 | | `$globalSetMockMode` | useFetch | 设置 Mock 模式(link/mock 切换) | | `$globalIsMockMode` | useFetch | 获取当前 Mock 模式状态 | | `$globalRedux` | useRedux | Redux Store 实例 | | `$globalReduxAction` | useRedux | Redux Action 加载 | | `$globalEventBus` | useEventBus | mitt 事件总线 | | `$globalConstant` | useConstant | 常量模块加载 | | `useNavigate` | useCustomNavigate | 自定义导航(缓存感知) | | `useLocation` | react-router-dom | 路由位置 | | `useRoutes` | react-router-dom | 路由匹配 | | `Navigate` | react-router-dom | 声明式导航 | | `useTranslation` | react-i18next | 国际化 Hook | ### 常量管理 常量采用模块化定义,通过 `$globalConstant` 统一访问,与 Redux / Service 使用相同的自动加载模式: ```js // src/constant/resultCode.js const SUCCESS_CODE = 20000; export { SUCCESS_CODE }; ``` ```js // src/constant/eventBus.js const GET_HOME_LIST = "GET_HOME_LIST"; const SET_HOME_LIST = "SET_HOME_LIST"; export { GET_HOME_LIST, SET_HOME_LIST }; ``` ```jsx // 页面中使用 const { SUCCESS_CODE } = $globalConstant("resultCode"); const { GET_HOME_LIST } = $globalConstant("eventBus"); if (res?.code === SUCCESS_CODE) { // 处理成功逻辑 } ``` > 新增常量文件只需在 `src/constant/` 下创建 `.js` 文件并导出即可,无需手动注册。 ### 模块化 Redux 约定每个模块包含三个文件,通过 `import.meta.glob` 自动加载: ``` src/redux/{模块名}/ ├── reduxType.js # Action 类型常量 ├── reduxAction.js # Action 创建函数 └── reduxReducer.js # Reducer 函数(默认导出) ``` ```jsx // 页面中使用 const { setShopNum } = $globalReduxAction("common"); const Home = (props) => { const { setShopNum } = props; return
...
; }; const mapStateToProps = (state) => state.common; const mapDispatchToProps = { setShopNum }; export default connect(mapStateToProps, mapDispatchToProps)(Home); ``` ### 请求封装 基于 Axios 的统一请求层,支持多种请求方式和数据格式: ```js // 拼接请求 URL const url = $globalRequestUrl({ url: "/getGoodsList" }); // 发起请求 const [data, err] = await $globalRequest(url, params, { method: "GET" }); ``` Service 层统一使用 `[data, err]` 元组模式返回,配合常量判断响应状态: ```jsx const { getGoodsNum } = $globalServicer("common"); const [res] = await getGoodsNum(); const { SUCCESS_CODE } = $globalConstant("resultCode"); if (res?.code === SUCCESS_CODE) { $globalRedux.dispatch({ type: "SET_SHOP_NUM", shopNum: res?.data || 0 }); } ``` 支持的请求方法:`GET`、`POST`、`POST_JSON`、`POST_FORMDATA`、`POST_FORM_URLENCODED`、`PUT`、`PUT_FORDATA`、`DELETE`、`JSONP` ### Mock 数据模式 项目内置了全局 Mock 模式,无需后端即可进行前端开发调试。通过登录页面右上角的下拉组件或代码 API 进行 link/mock 切换: **切换方式:** | 方式 | 说明 | |------|------| | 登录页下拉 | 页面右上角点击 link/mock 按钮,选择模式即可切换 | | 代码 API | `$globalSetMockMode(true)` 开启 / `$globalSetMockMode(false)` 关闭 | **工作原理:** ```js // 开启 Mock 模式后,$globalRequest 内部拦截所有请求 if (window.__MOCK_ENABLED__) { const mockConfig = matchMock(url); if (mockConfig) { return Promise.resolve({ data: mockConfig.response(params), status: 200 }); } // 未匹配到 mock 则走正常网络请求 } ``` **Mock 数据结构:** ``` mock/ ├── index.js # 入口聚合,构建 URL → handler 映射表,提供 matchMock() ├── auth.js # /auth/login ├── common.js # getGoodsNum、getLanguage、getRuotes ├── home.js # getCarousel、boutiqueGoods、recommendGoods ├── classify.js # getClassify、classifyGoods ├── shop.js # getCard、changeGoods、delCard ├── address.js # getAddersslist └── goods.js # getGoodsdetal ``` > Mock 数据覆盖 `js.md` 中定义的全部 15 个接口,切换后**全局生效**(登录页及后续所有页面的接口请求均走 mock 数据)。选择 link 模式时,接口地址恢复为 `.env` 文件中配置的 `VITE_BASE_URL`。 ### 国际化 基于 `i18next` + `react-i18next`,支持本地语言包和远程接口动态覆盖: ```jsx // 使用翻译 const { t } = useTranslation(); const title = t("common.home"); ``` 远程覆盖机制在应用初始化时自动执行,通过 `$globalConstant("resultCode").SUCCESS_CODE` 校验响应状态后加载远程语言包: ```js // src/hooks/useCommon.js const { getLanguage } = $globalServicer("common"); const [lang] = await getLanguage(); const { SUCCESS_CODE } = $globalConstant("resultCode"); if (lang?.code === SUCCESS_CODE) { Object.keys(lang?.data).forEach((key) => { i18n.addResourceBundle(key, "translation", lang?.data[key], true, true); }); } ``` ### 样式方案 - **CSS Modules** — `xxx.module.less` 文件自动开启局部作用域 - **:global 覆盖** — 在局部样式文件中用 `:global { }` 覆盖 UI 库样式 - **自动 rem 转换** — `postcss-pxtorem` (rootValue: 37.5) 自动将 px 转为 rem - **norem 跳过** — 类名以 `norem` 开头的不进行 rem 转换 ## 脚手架配置 ### Vite 插件模块化 在 `vite-config/plugins/` 目录下创建 `.js` 文件即可自动加载,无需手动注册: ```js // vite-config/index.js const loadPluginModules = async () => { const modulesPath = resolve(__dirname, "plugins"); const fileNames = fs.readdirSync(modulesPath); // 自动 import plugins/ 下所有 .js 文件 }; ``` ### 自定义 Vite 插件 | 插件 | 说明 | 钩子 | |------|------|------| | `vite-plugin-copy` | 构建后将环境配置文件复制到 dist | closeBundle | | `vite-plugin-zip` | 构建后将 dist 目录打包为 zip | closeBundle | | `vite-plugin-legacy` | 生成低版本浏览器兼容包 | - | | `vite-plugin-progress` | 构建时显示进度条 | - | ### 环境配置 ```bash vite-env/ ├── .env # 本地环境(默认) ├── .env.dev # 测试环境(npm run build:dev) └── .env.prod # 生产环境(npm run build:pro) ``` 通过 `import.meta.env.VITE_BASE_URL` 在代码中访问环境变量。 ## 相关链接 - [脚手架搭建 Demo (Vue/React + Vite/Farm/Rsbuild)](https://gitee.com/674074365/lan-project-cli) - [Vue 版本项目演示](https://www.lanlianjiu.xyz/#/login) - [Vue 版本项目代码](https://gitee.com/674074365/vue3-vant3-h5) - [React 版本项目演示](http://www.react.lanlianjiu.xyz/#/login) - [开发文档](http://www.reactappdoc.lanlianjiu.xyz) ## 贡献指南 1. Fork 本仓库 2. 创建特性分支 (`git checkout -b feat/your-feature`) 3. 提交变更 (`git commit -m 'feat: add your feature'`) 4. 推送分支 (`git push origin feat/your-feature`) 5. 创建 Pull Request ## License [MIT](./LICENSE)