# myreact-app **Repository Path**: lzh2019/myreact-app ## Basic Information - **Project Name**: myreact-app - **Description**: myreact-app 练习项目 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-05-13 - **Last Updated**: 2025-06-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # React + Vite This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. Currently, two official plugins are available: - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh ## Expanding the ESLint configuration If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. --- # rimraf 快速删除 开发过程中生成的临时文件 ``` 1. 安装 rimraf npm install rimraf -g 2. 使用命令删除 rimraf node_modules // 删除node_modules rimraf dist // 删除dist ``` --- # React 19 兼容问题 由于 React 19 调整了 react-dom 的导出方式,导致 antd 无法直接使用 ReactDOM.render 方法。因而使用 antd 会遇到以下问题: https://ant.design/docs/react/v5-for-19-cn 波纹特效无法正常工作 Modal、Notification、Message 等组件的静态方法无效 因而需要通过兼容配置,使 antd 在 React 19 中正常工作。 兼容方式 ``` npm install @ant-design/v5-patch-for-react-19 --save import '@ant-design/v5-patch-for-react-19'; ``` --- # React + JavaScript 项目完全可以集成 React Router 它是 React 生态中最流行的路由库,专为单页应用(SPA)设计。以下是详细整合步骤和示例: --- ### **1. 安装 React Router** 在项目根目录运行以下命令安装最新版本(当前为 v6): ```bash npm install react-router-dom # 或 yarn add react-router-dom ``` --- ### **2. 基础整合步骤** #### **① 包裹根组件(启用路由)** 在入口文件(如 `src/index.js`)中,用 `` 包裹整个应用: ```jsx import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( ); ``` #### **② 定义路由规则** 在 `App.js` 中使用 `` 和 `` 定义路由: ```jsx import { Routes, Route } from 'react-router-dom'; import Home from './pages/Home'; import About from './pages/About'; import User from './pages/User'; function App() { return ( } /> } /> } /> {/* 动态路由 */} ); } export default App; ``` #### **③ 创建页面组件** 在 `src/pages/` 下创建对应的组件文件(如 `Home.js`): ```jsx // src/pages/Home.js export default function Home() { return

Home Page

; } ``` --- ### **3. 关键功能实现** #### **① 动态路由参数** 在组件中通过 `useParams` 获取动态参数(如 `/user/123` 中的 `id`): ```jsx // src/pages/User.js import { useParams } from 'react-router-dom'; export default function User() { const { id } = useParams(); // 获取 :id 参数 return
User ID: {id}
; } ``` #### **② 导航跳转** 使用 `useNavigate` 进行编程式导航: ```jsx import { useNavigate } from 'react-router-dom'; function Home() { const navigate = useNavigate(); return ( ); } ``` 或使用 `` 组件实现声明式导航: ```jsx import { Link } from 'react-router-dom'; function Navbar() { return ( ); } ``` #### **③ 嵌套路由** 通过 `` 渲染子路由: ```jsx // 路由定义 }> } /> } /> // Dashboard.js 中放置 Outlet import { Outlet } from 'react-router-dom'; function Dashboard() { return (

Dashboard

{/* 子路由在此渲染 */}
); } ``` --- ### **4. 处理 404 页面** 添加 `*` 通配符路由作为兜底: ```jsx } /> } /> {/* 匹配所有未定义路径 */} ``` --- ### **5. 完整项目结构示例** ``` src/ ├── App.js ├── index.js ├── pages/ │ ├── Home.js │ ├── About.js │ ├── User.js │ └── NotFound.js ├── components/ │ └── Navbar.js └── styles/ └── main.css ``` --- ### **6. 注意事项** 1. **无需额外配置**:React Router 是纯客户端路由,无需服务端支持(除非用 SSR)。 2. **与状态管理兼容**:可自由搭配 Redux/Zustand 等状态库。 3. **Hash 路由**:如果项目部署在静态服务器且不支持 History API,可用 `` 替代 ``。 --- ### **为什么 React + JS 也能用?** - React Router 本身是用 JavaScript 编写的,类型支持(TypeScript)是可选的。 - 所有 API(如 `useParams`、`useNavigate`)在 JS 和 TS 中用法完全一致,只是 TS 会提供类型提示。 --- 通过以上步骤,你可以轻松在 React + JavaScript 项目中实现动态路由、导航和嵌套布局,构建完整的 SPA 应用! --- # 从 Vue 到 React 快速上手指南 (React + Ant Design) 作为已经熟悉 Vue、JavaScript 和 ElementUI 的开发者,你可以利用已有知识快速掌握 React 和 Ant Design。以下是针对性学习路径和实战建议: ## 1. 核心概念映射表 (Vue → React) | Vue 概念 | React 对应方案 | 差异说明 | |-------------------|------------------------|-------------------------| | 模板语法 | JSX | Vue 是模板,React 是 JS 扩展语法 | | v-model | 受控组件 | React 需要手动实现双向绑定 | | v-if/v-show | {condition && \} | React 用 JS 逻辑控制渲染 | | v-for | map() | 原理相同,语法不同 | | computed | useMemo | React 需要显式声明依赖 | | watch | useEffect | 依赖数组机制不同 | | 组件通信(props) | props | 机制非常相似 | | 组件通信(事件) | props传递回调函数 | Vue 有 $emit,React 直接传函数 | | 插槽 | props.children | 概念相似,实现不同 | | Vuex | Redux/Context | 状态管理理念相似 | | ElementUI | Ant Design | 都是优秀UI库,API设计不同 | ## 2. 快速入门步骤 (1-3天) ### 第一步:搭建环境 ```bash # 使用 Vite 创建 React + TypeScript 项目 npm create vite@latest my-react-app --template react-ts # 添加 Ant Design npm install antd @ant-design/icons ``` ### 第二步:配置 Ant Design ```typescript // src/App.tsx import { ConfigProvider } from 'antd'; import 'antd/dist/reset.css'; // 替代旧版的 import 'antd/dist/antd.css' function App() { return ( {/* 你的应用内容 */} ); } ``` ### 第三步:基础组件对比学习 #### 按钮组件 ```jsx // React + Ant Design import { Button } from 'antd'; // 对比 Vue + ElementUI 搜索 ``` #### 表单组件 ```jsx // React + Ant Design 受控组件写法 import { Form, Input, Button } from 'antd'; const [form] = Form.useForm();
console.log(values)}>
// 对比 Vue + ElementUI 提交 ``` ## 3. 关键差异点快速掌握 ### 状态管理 ```typescript // React 函数组件状态 import { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // 类似 Vue 的 ref // 类似 Vue 的 computed const double = useMemo(() => count * 2, [count]); // 类似 Vue 的 watch useEffect(() => { console.log('count changed:', count); }, [count]); return (

{count} x 2 = {double}

); } // 对比 Vue /* */ ``` ### 生命周期对应 | Vue 生命周期 | React Hook 等效 | |------------------|-------------------------| | beforeCreate | 不需要 (直接写在函数顶部) | | created | 不需要 (直接写在函数顶部) | | beforeMount | useEffect(() => {}, []) | | mounted | useEffect(() => {}, []) | | beforeUpdate | useEffect(() => {}) | | updated | useEffect(() => {}) | | beforeUnmount | useEffect(() => () => {})| | unmounted | useEffect(() => () => {})| ## 4. Ant Design 常用组件快速参考 ### 布局系统 ```jsx import { Layout, Menu } from 'antd'; const { Header, Sider, Content } = Layout;
Header
Main Content ``` ### 表格组件 ```jsx import { Table } from 'antd'; const columns = [ { title: 'Name', dataIndex: 'name' }, { title: 'Age', dataIndex: 'age' } ]; const data = [ { key: '1', name: 'John', age: 32 }, { key: '2', name: 'Jane', age: 28 } ]; ``` ### 消息提示 ```jsx import { message, notification } from 'antd'; // 类似 ElementUI 的 this.$message message.success('操作成功!'); // 类似 ElementUI 的 this.$notify notification.success({ message: '通知标题', description: '这是通知内容...' }); ``` ## 5. 实战项目结构建议 ``` src/ ├── assets/ # 静态资源 ├── components/ # 通用组件 ├── pages/ # 页面组件 ├── services/ # API服务(类似 Vue 的 api 目录) ├── stores/ # 状态管理(推荐使用 zustand 替代 Vuex) ├── utils/ # 工具函数 ├── App.tsx # 主组件 └── main.tsx # 入口文件 ``` ## 6. 推荐学习资源 1. **官方文档**: - [React 官方文档](https://react.dev/) (重点关注 Hooks 部分) - [Ant Design 文档](https://ant.design/docs/react/introduce-cn) 2. **速查表**: - [React 生命周期方法对应 Hooks](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/) - [Vue 到 React 的快速参考](https://vuetoreact.com/) 3. **实战教程**: - [Ant Design Pro 入门](https://pro.ant.design/zh-CN/docs/getting-started) - [React + AntD 后台管理系统实战](https://www.bilibili.com/video/BV1y44y1v7n2) ## 7. 常见问题解决方案 **Q: 如何实现类似 v-model 的双向绑定?** ```jsx // React 受控组件实现 const [value, setValue] = useState(''); setValue(e.target.value)} /> // 如果需要简化,可以封装自定义 Hook function useBind(initialValue) { const [value, setValue] = useState(initialValue); const onChange = (e) => setValue(e.target.value); return { value, onChange }; } // 使用 const bind = useBind(''); ``` **Q: 如何全局修改 AntD 组件默认属性?** ```jsx // 在 ConfigProvider 中统一配置 {/* 你的应用 */} ``` **Q: 如何实现路由权限控制?** ```jsx // 类似 Vue 的路由守卫 import { useLocation, Navigate } from 'react-router-dom'; function AuthRoute({ children }) { const location = useLocation(); const isLogin = /* 你的认证逻辑 */; if (!isLogin) { return ; } return children; } // 使用 } /> ``` 通过以上对比学习和实践,你应该可以在 1-2 周内快速上手 React + Ant Design 开发。记住,大部分前端概念是相通的,主要是语法和实现方式的差异。 --- # React 中子组件向父组件传值的机制 是的,React 完全支持子组件向父组件传值,这与 Vue 的 `$emit` 机制类似,但实现方式不同。以下是几种主要实现方式: ## 1. 通过回调函数 (最常用) 这是 React 中最典型的子传父通信方式,类似于 Vue 的 `$emit`。 ```jsx // 父组件 function ParentComponent() { const [valueFromChild, setValueFromChild] = useState(''); // 定义回调函数 const handleChildValue = (value) => { setValueFromChild(value); console.log('从子组件接收的值:', value); }; return (

来自子组件的值: {valueFromChild}

{/* 将回调函数作为prop传递给子组件 */}
); } // 子组件 function ChildComponent({ onValueChange }) { const [inputValue, setInputValue] = useState(''); const handleChange = (e) => { const value = e.target.value; setInputValue(value); // 调用父组件传递的回调函数 onValueChange(value); }; return ; } ``` ## 2. 使用 Context API (跨层级通信) 适合深层嵌套组件或需要跨多级组件通信的场景。 ```jsx // 创建Context const ValueContext = createContext({ value: '', setValue: () => {} }); // 父组件 function ParentComponent() { const [value, setValue] = useState(''); return (

来自子组件的值: {value}

); } // 子组件 function ChildComponent() { const { setValue } = useContext(ValueContext); const [inputValue, setInputValue] = useState(''); const handleChange = (e) => { const value = e.target.value; setInputValue(value); setValue(value); // 通过Context更新父组件状态 }; return ; } ``` ## 3. 使用状态管理库 (Redux/Zustand等) 适合大型应用或全局状态管理。 ```jsx // 使用Zustand示例 import { create } from 'zustand'; // 创建store const useStore = create((set) => ({ valueFromChild: '', setValueFromChild: (value) => set({ valueFromChild: value }) })); // 父组件 function ParentComponent() { const valueFromChild = useStore((state) => state.valueFromChild); return (

来自子组件的值: {valueFromChild}

); } // 子组件 function ChildComponent() { const setValueFromChild = useStore((state) => state.setValueFromChild); const [inputValue, setInputValue] = useState(''); const handleChange = (e) => { const value = e.target.value; setInputValue(value); setValueFromChild(value); // 更新全局状态 }; return ; } ``` ## 4. 使用 ref 和命令式方法 (不推荐但可行) 适用于需要直接调用子组件方法的场景。 ```jsx // 子组件 (使用 forwardRef) const ChildComponent = forwardRef((props, ref) => { const [value, setValue] = useState(''); // 向父组件暴露方法 useImperativeHandle(ref, () => ({ getValue: () => value, setValue: (newValue) => setValue(newValue) })); return setValue(e.target.value)} />; }); // 父组件 function ParentComponent() { const childRef = useRef(); const handleClick = () => { // 调用子组件暴露的方法 alert('子组件的当前值: ' + childRef.current.getValue()); }; return (
); } ``` ## 与 Vue 的对比 | Vue 方式 | React 等效方式 | 说明 | |-------------------|------------------------|------------------------| | `this.$emit('event', value)` | 传递回调函数作为prop | React 更显式 | | v-model + .sync | 受控组件 + 回调函数 | React 需要更多样板代码 | | provide/inject | Context API | 概念相似 | | Vuex | Redux/Zustand等 | 状态管理库理念相似 | ## 最佳实践建议 1. **优先使用回调函数**:对于简单的父子通信,回调函数是最直接和React风格的方式 2. **避免过度使用ref**:命令式操作违背React的数据流原则 3. **合理使用Context**:当组件层级较深时,Context比逐层传递props更优雅 4. **状态管理库选择**:只有真正需要全局状态时才引入Redux等库 记住,React的数据流是单向的(父→子),子组件向父组件通信本质上是通过父组件"向下传递"的回调函数实现的,这与Vue的双向绑定理念不同,但最终能达到相同的效果。 --- # 在 React 项目中使用 Mock 模拟后端接口 作为从 Vue 转 React 的开发者,你已经熟悉前端 mock 数据的概念。以下是 React 项目中几种常用的 mock 后端接口方案: ## 1. 使用 Mock.js (简单快速) 适合快速搭建 mock 数据,特别适合从 Vue 转 React 的开发者,因为用法与 Vue 中类似。 ```bash npm install mockjs --save-dev ``` ### 基本使用方式 ```javascript // src/mock/user.js import Mock from 'mockjs'; Mock.mock('/api/login', 'post', { code: 200, message: 'success', data: { token: Mock.Random.guid(), username: Mock.Random.cname(), 'roles|1': ['admin', 'editor', 'visitor'] } }); Mock.mock('/api/user/list', 'get', { 'list|10': [{ 'id|+1': 1, name: Mock.Random.cname(), 'age|18-60': 1, address: Mock.Random.county(true) }] }); ``` ### 在项目中启用 Mock ```javascript // src/main.jsx 或入口文件 if (process.env.NODE_MOCK === 'true') { require('./mock'); // 导入所有mock文件 } ``` 然后在 package.json 中配置脚本: ```json { "scripts": { "dev:mock": "NODE_MOCK=true vite", "dev": "vite" } } ``` ## 2. 使用 Vite 插件 vite-plugin-mock (推荐) 这是 Vite 生态中最流行的 mock 方案,支持热更新。 ```bash npm install vite-plugin-mock mockjs --save-dev ``` ### 配置 vite.config.js ```javascript import { viteMockServe } from 'vite-plugin-mock'; export default defineConfig({ plugins: [ viteMockServe({ mockPath: 'mock', // mock文件目录 localEnabled: true, // 开发环境启用 prodEnabled: false, // 生产环境禁用 logger: true // 控制台显示请求日志 }) ] }); ``` ### 创建 mock 文件 ```typescript // mock/user.ts import { MockMethod } from 'vite-plugin-mock'; export default [ { url: '/api/login', method: 'post', response: ({ body }) => { if (body.username === 'admin' && body.password === '123456') { return { code: 200, message: 'success', data: { token: 'fake-jwt-token', username: 'admin', roles: ['admin'] } }; } return { code: 401, message: '用户名或密码错误' }; } }, { url: '/api/user/list', method: 'get', timeout: 1000, // 模拟网络延迟 response: { code: 200, 'list|10': [ { 'id|+1': 1, name: '@cname', 'age|18-60': 1, address: '@county(true)' } ] } } ] as MockMethod[]; ``` ## 3. 使用 MSW (Mock Service Worker - 最接近真实网络请求) MSW 通过 Service Worker 拦截请求,是最接近真实网络环境的 mock 方案。 ```bash npm install msw --save-dev npx msw init public/ --save ``` ### 配置 mock handlers ```javascript // src/mocks/handlers.js import { rest } from 'msw'; export const handlers = [ rest.post('/api/login', (req, res, ctx) => { const { username, password } = req.body; if (username === 'admin' && password === '123456') { return res( ctx.delay(150), // 模拟网络延迟 ctx.json({ code: 200, data: { token: 'fake-jwt-token', username: 'admin', roles: ['admin'] } }) ); } return res( ctx.status(401), ctx.json({ message: '用户名或密码错误' }) ); }), rest.get('/api/user/list', (req, res, ctx) => { return res( ctx.delay(500), ctx.json({ code: 200, list: Array(10).fill(0).map((_, i) => ({ id: i + 1, name: `用户${i + 1}`, age: 18 + Math.floor(Math.random() * 42), address: `地址${i + 1}` })) }) ); }) ]; ``` ### 启动 Service Worker ```javascript // src/mocks/browser.js import { setupWorker } from 'msw'; import { handlers } from './handlers'; export const worker = setupWorker(...handlers); ``` ### 在开发环境启用 ```javascript // src/main.jsx if (process.env.NODE_ENV === 'development') { const { worker } = require('./mocks/browser'); worker.start(); } ``` ## 4. 使用 json-server (快速搭建完整 REST API) 适合需要完整 RESTful API 接口的场景。 ```bash npm install json-server --save-dev ``` ### 创建 db.json ```json { "users": [ { "id": 1, "name": "张三", "age": 25 }, { "id": 2, "name": "李四", "age": 30 } ], "posts": [ { "id": 1, "title": "文章1", "author": "张三" }, { "id": 2, "title": "文章2", "author": "李四" } ] } ``` ### 配置 package.json ```json { "scripts": { "mock:server": "json-server --watch db.json --port 3001", "dev": "vite", "dev:with-mock": "concurrently \"npm run mock:server\" \"npm run dev\"" } } ``` ## 实际项目中使用示例 ### 封装请求函数 ```typescript // src/api/request.ts import axios from 'axios'; const instance = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 10000 }); // 请求拦截器 instance.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // 响应拦截器 instance.interceptors.response.use( response => response.data, error => { if (error.response.status === 401) { // 处理未授权 } return Promise.reject(error); } ); export default instance; ``` ### 定义 API 接口 ```typescript // src/api/user.ts import request from './request'; export const login = (data: { username: string; password: string }) => { return request.post('/login', data); }; export const getUserList = (params?: { page: number; size: number }) => { return request.get('/user/list', { params }); }; ``` ### 在组件中使用 ```tsx import { useEffect, useState } from 'react'; import { getUserList } from '@/api/user'; function UserList() { const [users, setUsers] = useState([]); useEffect(() => { const fetchUsers = async () => { try { const res = await getUserList(); setUsers(res.list); } catch (error) { console.error('获取用户列表失败', error); } }; fetchUsers(); }, []); return (
{users.map(user => (
{user.name}
))}
); } ``` ## 各方案对比 | 方案 | 优点 | 缺点 | 适用场景 | |-------------------|-----------------------------|-----------------------------|-------------------------| | Mock.js | 简单快速,学习成本低 | 无法拦截真实请求,需要修改请求基址 | 简单项目,快速原型开发 | | vite-plugin-mock | 集成在Vite中,支持热更新 | 仅限Vite项目 | 使用Vite的React项目 | | MSW | 拦截真实网络请求,最接近生产环境 | 配置稍复杂 | 需要模拟真实网络请求的中大型项目 | | json-server | 提供完整REST API,支持增删改查 | 需要运行单独服务 | 需要完整后端API接口的项目 | | 本地JSON文件 | 最简单 | 只能模拟GET请求,无法模拟复杂交互 | 静态数据展示 | ## 最佳实践建议 1. **开发环境与生产环境分离**:确保mock只在开发环境启用 2. **模拟网络延迟**:添加适当延迟(100-500ms)使体验更真实 3. **错误场景模拟**:不要只模拟成功情况,也要模拟401、500等错误 4. **保持接口一致性**:mock接口应该与真实后端接口保持相同结构和行为 5. **文档化mock数据**:为团队维护一份mock接口文档 选择哪种方案取决于项目需求: - 小型项目:Mock.js 或 vite-plugin-mock - 中大型项目:MSW - 需要完整REST API:json-server 从你的 Vue 背景来看,vite-plugin-mock 可能是最平滑的过渡方案,因为它与 Vue 生态中的 vite 插件使用方式类似。 --- ## 有了react Context 是不是就没必要再使用 zustand 了 不完全是。 对比说明: React Context 适合管理 全局但变化不频繁 的数据(如主题、登录用户、菜单、权限等),用法简单,适合小型或中型项目。 zustand 是一个轻量级的全局状态管理库,适合管理 复杂、频繁变化 的全局状态,支持更灵活的状态拆分、选择性订阅、持久化等,性能更优,代码更简洁,适合中大型项目或需要响应式全局状态的场景。 结论: 如果你的项目只需要简单的全局状态管理,React Context 足够用,可以不用 zustand。 如果你需要更强大的状态管理能力(如模块化、性能优化、复杂业务状态),可以用 zustand 替代或配合 Context。 两者可以并存,分别管理不同类型的全局状态。 实际开发中: 小项目/简单全局数据:用 Context 就够了。 大项目/复杂状态/高性能需求:推荐 zustand 或 redux。 总结: 有了 React Context,不一定非要用 zustand,但如果你有更复杂的全局状态管理需求,zustand 会更好用 --- ## React Context 会不会和zustand 起冲突 不会冲突,React Context 和 zustand 可以同时使用,也不会互相影响。 它们都是全局状态管理方案,但实现机制不同,互不干扰。 你可以用 Context 管理一部分全局状态(如主题、用户信息),用 zustand 管理另一部分(如复杂业务状态、频繁变化的数据)。 在同一个项目中,组件可以自由选择用 Context 还是 zustand,互不影响。 总结: Context 和 zustand 可以并存,不会冲突。实际开发中可以根据需求灵活选择或组合使用 ---