四、React的基本使用
(一)基础代码结构
1. JSX 核心语法
const element = (
<div className="container">
<h1>Hello, React 18!</h1>
<p>{new Date().toLocaleTimeString()}</p>
</div>
);
关键规则:
-
单根节点:必须用
<div>
或<>
(Fragment)包裹元素 -
属性命名:使用
camelCase
(如onClick
而非onclick
) -
表达式插值:
{}
内可嵌入 JavaScript 表达式
2. 组件类型对比
实践:React 18 推荐函数组件 + Hooks 模式
(二)开发环境配置
1. 创建项目(JSX 版)
npx create-react-app my-app
cd my-app
npm start
目录结构:
src/
├── App.js # 根组件
├── index.js # 入口文件
└── components/ # 子组件目录
复制
2. 启用 React 18 并发渲染
index.jsx
//引入react核心库
import React from 'react'
//引入ReactDOM
import { createRoot } from 'react-dom/client';
//引入App
import App from './App'
const root = createRoot(document.getElementById('root'));
root.render(<App />); // 启用并发渲染能力[2,8](@ref)
(三)核心库生态
(四)第一个 React 应用:交互式计数器
import { useState } from 'react';
import './App.css'
function App() {
const Counter = ({ initialValue = 0 }) => {
const [count, setCount] = useState(initialValue);
// 自动批处理示例:合并两次更新[4,8](@ref)
const doubleIncrement = () => {
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
};
return (
<div className="counter">
<p>Current: {count}</p>
<button onClick={() => setCount(count - 1)}>Decrement</button>
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={doubleIncrement}>+2 (Batched)</button>
</div>
);
};
return (
<Counter />
);
}
效果图:
(五)常见效果实现
1. 条件渲染
function UserStatus({ isLogin }) {
return (
<div>
{isLogin ? <span>Welcome back!</span> : <button>Login</button>}
</div>
);
}
- 功能说明:根据用户登录状态 isLogin 动态渲染不同内容。
- 实现原理:
-
- 使用 三元运算符 condition ? A : B,若 isLogin 为 true 则显示欢迎信息,否则显示登录按钮。
-
- 逻辑清晰,适合两种状态的简单切换。
- 最佳实践:
-
- 对于多状态条件(如超过两种),可改用 switch 语句或拆分为独立组件。
-
- 避免在 JSX 内写复杂逻辑,可将条件判断提取为变量或函数。
2. 动态列表渲染(Key 优化 Diff 算法)
const FileList = ({ files }) => (
<ul>
{files.map(file => (
<li key={file.id}>
<span>{file.name}</span>
<span>{file.size} KB</span>
</li>
))}
</ul>
);
- 功能说明:遍历文件数组,动态生成列表项。
- 核心机制:
-
- map() 方法:将数组 files 映射为
<li>
元素列表。
- map() 方法:将数组 files 映射为
-
- key 属性:
-
-
- 为每个列表项提供唯一标识(如 file.id),帮助 React 识别元素变化9。
-
-
-
- 避免使用数组索引(如 index),因为索引在增删元素时会变化,导致渲染错误或性能下降910。
-
- 性能优化:
-
- Key 值稳定时,React 的 Diff 算法 能高效更新 DOM(仅重排变化的元素)。
3. 异步加载(Suspense)
import { lazy, Suspense } from 'react';
const LazyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent /> // 代码分割
</Suspense>
);
}
- 功能说明:实现组件的按需加载(代码分割),提升首屏性能。
- 核心机制:
-
- lazy():动态导入组件(如 import('./HeavyComponent')),生成一个异步加载的组件。
-
- Suspense:
-
-
- 包裹异步组件,在加载过程中显示 fallback 内容(如 Loading 动画)。
-
-
-
- 避免页面空白,优化用户体验。
-
- 适用场景:
-
- 大型组件(如弹窗、图表库)或路由级代码分割。
4. 表单处理
function FileUpload() {
const [file, setFile] = useState(null);
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('file', file);
await axios.post('/api/upload', formData);
};
return (
<form onSubmit={handleSubmit}>
<input type="file" onChange={e => setFile(e.target.files[0])} />
<button disabled={!file}>Upload</button>
</form>
);
}
- 功能说明:实现文件选择与上传功能。
- 关键步骤:
-
- 状态管理:useState 存储用户选择的文件对象。
-
- 表单提交:
-
-
- 阻止默认跳转(e.preventDefault())。
-
-
-
- 通过 FormData 封装文件数据,使用 axios 发送到后端。
-
-
- 交互优化:disabled={!file} 确保未选择文件时按钮不可点击。
- 扩展实践:
-
- 添加进度条(axios 的 onUploadProgress 回调)或错误处理(try/catch)。
-
- 支持多文件上传:将 files[0] 改为遍历 files 数组。
总结与最佳实践
(六)调试与开发工具
1. React Develpoer Tools
功能亮点:
- 组件树可视化
- Hooks 值监控
- Profiler 性能分析
2. 调试技巧
// 错误边界(React 18 增强)
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
componentDidCatch(error, info) {
console.error('Error:', error, info.componentStack);
}
}
// 严格模式检测
<React.StrictMode>
<App />
</React.StrictMode>
3. 性能优化
// 使用 memo 避免重复渲染
const MemoList = React.memo(FileList);
// 生产环境构建
npm run build // 生成优化包
npx source-map-explorer build/static/js/*.js // 分析包体积[4](@ref)
结语
React 18 的 并发渲染(通过 createRoot 启用)和 自动批处理 显著提升了应用性能,结合 JSX 的灵活语法,可快速构建高性能应用。关键实践包括:
- 函数组件 + Hooks 作为主流开发模式
- Suspense 实现异步加载和代码分割
- 使用 React.memo 和虚拟列表优化渲染
- 通过 DevTools 分析组件性能