Appearance
性能优化实战对比
学习目标
通过本章学习,你将全面掌握:
- 各种性能优化方案的对比
- 性能测量工具的使用
- 真实场景的优化策略
- 优化前后的性能差异
- 性能优化的最佳实践
- 常见性能陷阱
- React 19的自动优化
- 性能监控和分析
第一部分:优化方案全面对比
1.1 未优化vs完全优化
jsx
// ========== 未优化版本 ==========
function UnoptimizedApp() {
const [count, setCount] = useState(0);
const [items, setItems] = useState(
Array.from({ length: 1000 }, (_, i) => ({
id: i,
name: `Item ${i}`,
value: Math.random()
}))
);
// 问题1:每次渲染都过滤
const filteredItems = items.filter(item => item.id % 2 === 0);
// 问题2:每次渲染都排序
const sortedItems = filteredItems.sort((a, b) => b.value - a.value);
// 问题3:每次渲染创建新函数
const handleClick = (id) => {
console.log('点击:', id);
};
// 问题4:每次渲染创建新对象
const config = {
showActions: true,
editable: false
};
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
更新Count: {count}
</button>
<p>共 {sortedItems.length} 项</p>
{sortedItems.map(item => (
<RegularItem
key={item.id}
item={item}
onClick={handleClick}
config={config}
/>
))}
</div>
);
}
function RegularItem({ item, onClick, config }) {
console.log('Item渲染:', item.id);
return (
<div onClick={() => onClick(item.id)}>
{item.name}: {item.value.toFixed(3)}
</div>
);
}
// ========== 完全优化版本 ==========
function OptimizedApp() {
const [count, setCount] = useState(0);
const [items, setItems] = useState(
Array.from({ length: 1000 }, (_, i) => ({
id: i,
name: `Item ${i}`,
value: Math.random()
}))
);
// 优化1:使用useMemo缓存过滤结果
const filteredItems = useMemo(() => {
console.log('执行过滤');
return items.filter(item => item.id % 2 === 0);
}, [items]);
// 优化2:使用useMemo缓存排序结果
const sortedItems = useMemo(() => {
console.log('执行排序');
return [...filteredItems].sort((a, b) => b.value - a.value);
}, [filteredItems]);
// 优化3:使用useCallback缓存函数
const handleClick = useCallback((id) => {
console.log('点击:', id);
}, []);
// 优化4:使用useMemo缓存配置对象
const config = useMemo(() => ({
showActions: true,
editable: false
}), []);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
更新Count: {count}
</button>
<p>共 {sortedItems.length} 项</p>
{sortedItems.map(item => (
<OptimizedItem
key={item.id}
item={item}
onClick={handleClick}
config={config}
/>
))}
</div>
);
}
// 优化5:使用React.memo包裹组件
const OptimizedItem = React.memo(function Item({ item, onClick, config }) {
console.log('Item渲染:', item.id);
return (
<div onClick={() => onClick(item.id)}>
{item.name}: {item.value.toFixed(3)}
</div>
);
});1.2 性能对比表
jsx
/*
性能对比:
未优化版本:
- 每次count变化时:
- 过滤1000项:~2ms
- 排序500项:~1ms
- 渲染500个组件:~50ms
- 总计:~53ms
- 所有Item组件都重新渲染
优化版本:
- 每次count变化时:
- 过滤:跳过(使用缓存)
- 排序:跳过(使用缓存)
- 渲染:跳过(React.memo)
- 总计:~1ms
- 没有Item组件重新渲染
性能提升:53倍
*/第二部分:性能测量工具
2.1 使用React DevTools Profiler
jsx
import { Profiler } from 'react';
function ProfiledApp() {
const [count, setCount] = useState(0);
const onRenderCallback = (
id, // Profiler的id
phase, // "mount" 或 "update"
actualDuration, // 本次渲染耗时
baseDuration, // 不使用memo的估计耗时
startTime, // 开始渲染的时间
commitTime // 提交更新的时间
) => {
console.log({
id,
phase,
actualDuration: actualDuration.toFixed(2) + 'ms',
baseDuration: baseDuration.toFixed(2) + 'ms',
improvement: ((baseDuration - actualDuration) / baseDuration * 100).toFixed(1) + '%'
});
};
return (
<Profiler id="App" onRender={onRenderCallback}>
<div>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
<ExpensiveComponent />
</div>
</Profiler>
);
}2.2 自定义性能监控
jsx
function PerformanceMonitor() {
const renderTimes = useRef([]);
const renderCount = useRef(0);
const startTime = useRef(performance.now());
useEffect(() => {
const endTime = performance.now();
const duration = endTime - startTime.current;
renderTimes.current.push(duration);
renderCount.current++;
console.log(`渲染 #${renderCount.current}: ${duration.toFixed(2)}ms`);
if (renderTimes.current.length >= 10) {
const average = renderTimes.current.reduce((a, b) => a + b, 0) / renderTimes.current.length;
console.log(`平均渲染时间: ${average.toFixed(2)}ms`);
}
});
// 记录开始时间
startTime.current = performance.now();
return <div>性能监控组件</div>;
}2.3 性能测试套件
jsx
function PerformanceTestSuite() {
const [testResults, setTestResults] = useState([]);
const runTest = (name, testFn) => {
const iterations = 100;
const times = [];
for (let i = 0; i < iterations; i++) {
const start = performance.now();
testFn();
const end = performance.now();
times.push(end - start);
}
const average = times.reduce((a, b) => a + b, 0) / times.length;
const min = Math.min(...times);
const max = Math.max(...times);
setTestResults(prev => [...prev, {
name,
average: average.toFixed(3),
min: min.toFixed(3),
max: max.toFixed(3)
}]);
};
const runAllTests = () => {
setTestResults([]);
runTest('未优化渲染', () => {
// 测试未优化版本
});
runTest('优化渲染', () => {
// 测试优化版本
});
};
return (
<div>
<button onClick={runAllTests}>运行性能测试</button>
<table>
<thead>
<tr>
<th>测试名称</th>
<th>平均耗时</th>
<th>最小耗时</th>
<th>最大耗时</th>
</tr>
</thead>
<tbody>
{testResults.map((result, i) => (
<tr key={i}>
<td>{result.name}</td>
<td>{result.average}ms</td>
<td>{result.min}ms</td>
<td>{result.max}ms</td>
</tr>
))}
</tbody>
</table>
</div>
);
}第三部分:真实场景优化
3.1 场景1:社交媒体Feed
jsx
// ===== 未优化版本 =====
function UnoptimizedFeed() {
const [posts, setPosts] = useState([]);
const [likedPosts, setLikedPosts] = useState(new Set());
const handleLike = (postId) => {
setLikedPosts(prev => {
const newSet = new Set(prev);
if (newSet.has(postId)) {
newSet.delete(postId);
} else {
newSet.add(postId);
}
return newSet;
});
};
return (
<div>
{posts.map(post => (
<FeedPost
key={post.id}
post={post}
isLiked={likedPosts.has(post.id)}
onLike={() => handleLike(post.id)}
/>
))}
</div>
);
}
function FeedPost({ post, isLiked, onLike }) {
console.log('FeedPost渲染:', post.id);
return (
<div className="post">
<h3>{post.title}</h3>
<p>{post.content}</p>
<button onClick={onLike}>
{isLiked ? '已点赞' : '点赞'} ({post.likes})
</button>
</div>
);
}
// ===== 优化版本 =====
function OptimizedFeed() {
const [posts, setPosts] = useState([]);
const [likedPosts, setLikedPosts] = useState(new Set());
// 使用useCallback缓存点赞函数
const handleLike = useCallback((postId) => {
setLikedPosts(prev => {
const newSet = new Set(prev);
if (newSet.has(postId)) {
newSet.delete(postId);
} else {
newSet.add(postId);
}
return newSet;
});
}, []);
return (
<div>
{posts.map(post => (
<MemoFeedPost
key={post.id}
post={post}
isLiked={likedPosts.has(post.id)}
onLike={handleLike}
/>
))}
</div>
);
}
// 使用React.memo + 自定义比较
const MemoFeedPost = React.memo(
function FeedPost({ post, isLiked, onLike }) {
console.log('FeedPost渲染:', post.id);
const handleClick = useCallback(() => {
onLike(post.id);
}, [post.id, onLike]);
return (
<div className="post">
<h3>{post.title}</h3>
<p>{post.content}</p>
<button onClick={handleClick}>
{isLiked ? '已点赞' : '点赞'} ({post.likes})
</button>
</div>
);
},
(prevProps, nextProps) => {
// 自定义比较:只比较需要的属性
return prevProps.post.id === nextProps.post.id &&
prevProps.isLiked === nextProps.isLiked;
}
);3.2 场景2:电商商品列表
jsx
// ===== 未优化版本 =====
function UnoptimizedProductList() {
const [products] = useState(generateProducts(500));
const [filter, setFilter] = useState('all');
const [sortBy, setSortBy] = useState('name');
const [cart, setCart] = useState([]);
// 问题:每次渲染都过滤和排序
const filteredProducts = products.filter(p => {
if (filter === 'all') return true;
return p.category === filter;
});
const sortedProducts = filteredProducts.sort((a, b) => {
if (sortBy === 'name') return a.name.localeCompare(b.name);
if (sortBy === 'price') return a.price - b.price;
return 0;
});
const addToCart = (product) => {
setCart([...cart, product]);
};
return (
<div>
<div>
<select value={filter} onChange={e => setFilter(e.target.value)}>
<option value="all">全部</option>
<option value="electronics">电子产品</option>
<option value="clothing">服装</option>
</select>
<select value={sortBy} onChange={e => setSortBy(e.target.value)}>
<option value="name">按名称</option>
<option value="price">按价格</option>
</select>
</div>
<div className="product-grid">
{sortedProducts.map(product => (
<ProductCard
key={product.id}
product={product}
onAddToCart={() => addToCart(product)}
/>
))}
</div>
</div>
);
}
function ProductCard({ product, onAddToCart }) {
console.log('ProductCard渲染:', product.id);
return (
<div className="product-card">
<h3>{product.name}</h3>
<p>¥{product.price}</p>
<button onClick={onAddToCart}>加入购物车</button>
</div>
);
}
// ===== 优化版本 =====
function OptimizedProductList() {
const [products] = useState(generateProducts(500));
const [filter, setFilter] = useState('all');
const [sortBy, setSortBy] = useState('name');
const [cart, setCart] = useState([]);
// 优化:使用useMemo缓存过滤结果
const filteredProducts = useMemo(() => {
console.log('执行过滤');
return products.filter(p => {
if (filter === 'all') return true;
return p.category === filter;
});
}, [products, filter]);
// 优化:使用useMemo缓存排序结果
const sortedProducts = useMemo(() => {
console.log('执行排序');
return [...filteredProducts].sort((a, b) => {
if (sortBy === 'name') return a.name.localeCompare(b.name);
if (sortBy === 'price') return a.price - b.price;
return 0;
});
}, [filteredProducts, sortBy]);
// 优化:使用useCallback缓存函数
const addToCart = useCallback((product) => {
setCart(prev => [...prev, product]);
}, []);
return (
<div>
<div>
<select value={filter} onChange={e => setFilter(e.target.value)}>
<option value="all">全部</option>
<option value="electronics">电子产品</option>
<option value="clothing">服装</option>
</select>
<select value={sortBy} onChange={e => setSortBy(e.target.value)}>
<option value="name">按名称</option>
<option value="price">按价格</option>
</select>
</div>
<div className="product-grid">
{sortedProducts.map(product => (
<MemoProductCard
key={product.id}
product={product}
onAddToCart={addToCart}
/>
))}
</div>
</div>
);
}
const MemoProductCard = React.memo(function ProductCard({ product, onAddToCart }) {
console.log('ProductCard渲染:', product.id);
const handleClick = useCallback(() => {
onAddToCart(product);
}, [product, onAddToCart]);
return (
<div className="product-card">
<h3>{product.name}</h3>
<p>¥{product.price}</p>
<button onClick={handleClick}>加入购物车</button>
</div>
);
});
function generateProducts(count) {
return Array.from({ length: count }, (_, i) => ({
id: i,
name: `Product ${i}`,
price: Math.floor(Math.random() * 1000) + 100,
category: ['electronics', 'clothing'][Math.floor(Math.random() * 2)]
}));
}3.3 场景3:数据仪表板
jsx
// ===== 未优化版本 =====
function UnoptimizedDashboard({ rawData }) {
const [timeRange, setTimeRange] = useState('day');
const [metric, setMetric] = useState('revenue');
// 问题:每次渲染都处理数据
const processedData = rawData.filter(d => {
const date = new Date(d.date);
const now = new Date();
if (timeRange === 'day') {
return date.toDateString() === now.toDateString();
} else if (timeRange === 'week') {
const weekAgo = new Date(now - 7 * 24 * 60 * 60 * 1000);
return date >= weekAgo;
}
return true;
}).map(d => ({
...d,
value: metric === 'revenue' ? d.revenue : d.orders
}));
const total = processedData.reduce((sum, d) => sum + d.value, 0);
const average = total / processedData.length;
return (
<div>
<select value={timeRange} onChange={e => setTimeRange(e.target.value)}>
<option value="day">今天</option>
<option value="week">本周</option>
<option value="month">本月</option>
</select>
<select value={metric} onChange={e => setMetric(e.target.value)}>
<option value="revenue">收入</option>
<option value="orders">订单数</option>
</select>
<StatCard label="总计" value={total} />
<StatCard label="平均" value={average} />
<Chart data={processedData} />
</div>
);
}
function StatCard({ label, value }) {
console.log('StatCard渲染:', label);
return (
<div>
<h3>{label}</h3>
<p>{value.toFixed(2)}</p>
</div>
);
}
function Chart({ data }) {
console.log('Chart渲染');
return <div>图表: {data.length} 个数据点</div>;
}
// ===== 优化版本 =====
function OptimizedDashboard({ rawData }) {
const [timeRange, setTimeRange] = useState('day');
const [metric, setMetric] = useState('revenue');
// 优化:使用useMemo缓存数据处理
const processedData = useMemo(() => {
console.log('处理数据');
return rawData.filter(d => {
const date = new Date(d.date);
const now = new Date();
if (timeRange === 'day') {
return date.toDateString() === now.toDateString();
} else if (timeRange === 'week') {
const weekAgo = new Date(now - 7 * 24 * 60 * 60 * 1000);
return date >= weekAgo;
}
return true;
}).map(d => ({
...d,
value: metric === 'revenue' ? d.revenue : d.orders
}));
}, [rawData, timeRange, metric]);
// 优化:使用useMemo缓存统计计算
const statistics = useMemo(() => {
console.log('计算统计');
const total = processedData.reduce((sum, d) => sum + d.value, 0);
const average = processedData.length > 0 ? total / processedData.length : 0;
const max = Math.max(...processedData.map(d => d.value));
const min = Math.min(...processedData.map(d => d.value));
return { total, average, max, min };
}, [processedData]);
return (
<div>
<select value={timeRange} onChange={e => setTimeRange(e.target.value)}>
<option value="day">今天</option>
<option value="week">本周</option>
<option value="month">本月</option>
</select>
<select value={metric} onChange={e => setMetric(e.target.value)}>
<option value="revenue">收入</option>
<option value="orders">订单数</option>
</select>
<MemoStatCard label="总计" value={statistics.total} />
<MemoStatCard label="平均" value={statistics.average} />
<MemoStatCard label="最大" value={statistics.max} />
<MemoStatCard label="最小" value={statistics.min} />
<MemoChart data={processedData} />
</div>
);
}
const MemoStatCard = React.memo(function StatCard({ label, value }) {
console.log('StatCard渲染:', label);
return (
<div className="stat-card">
<h3>{label}</h3>
<p>{value.toFixed(2)}</p>
</div>
);
});
const MemoChart = React.memo(function Chart({ data }) {
console.log('Chart渲染');
// 图表渲染逻辑
return (
<div className="chart">
图表: {data.length} 个数据点
</div>
);
});3.4 场景4:聊天应用
jsx
// ===== 优化版聊天应用 =====
function OptimizedChatApp() {
const [messages, setMessages] = useState([]);
const [inputText, setInputText] = useState('');
const [filter, setFilter] = useState('all');
// 过滤消息
const filteredMessages = useMemo(() => {
if (filter === 'all') return messages;
return messages.filter(m => m.type === filter);
}, [messages, filter]);
// 发送消息
const sendMessage = useCallback(() => {
if (inputText.trim()) {
setMessages(prev => [
...prev,
{
id: Date.now(),
text: inputText,
timestamp: Date.now(),
type: 'sent'
}
]);
setInputText('');
}
}, [inputText]);
// 删除消息
const deleteMessage = useCallback((id) => {
setMessages(prev => prev.filter(m => m.id !== id));
}, []);
return (
<div className="chat-app">
<MessageFilter filter={filter} onFilterChange={setFilter} />
<MemoMessageList
messages={filteredMessages}
onDelete={deleteMessage}
/>
<MemoMessageInput
value={inputText}
onChange={setInputText}
onSend={sendMessage}
/>
</div>
);
}
const MemoMessageList = React.memo(function MessageList({ messages, onDelete }) {
console.log('MessageList渲染');
return (
<div className="message-list">
{messages.map(message => (
<MemoMessage
key={message.id}
message={message}
onDelete={onDelete}
/>
))}
</div>
);
});
const MemoMessage = React.memo(function Message({ message, onDelete }) {
console.log('Message渲染:', message.id);
const handleDelete = useCallback(() => {
onDelete(message.id);
}, [message.id, onDelete]);
return (
<div className={`message ${message.type}`}>
<p>{message.text}</p>
<span className="timestamp">
{new Date(message.timestamp).toLocaleTimeString()}
</span>
<button onClick={handleDelete}>删除</button>
</div>
);
});
const MemoMessageInput = React.memo(function MessageInput({ value, onChange, onSend }) {
console.log('MessageInput渲染');
const handleKeyPress = (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
onSend();
}
};
return (
<div className="message-input">
<input
value={value}
onChange={e => onChange(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="输入消息..."
/>
<button onClick={onSend}>发送</button>
</div>
);
});第四部分:性能优化检查清单
4.1 检查项目
jsx
// 性能优化检查清单
const PerformanceChecklist = {
// 1. State管理
stateManagement: {
question: '是否合理拆分State?',
bad: '一个大State对象',
good: '多个小State'
},
// 2. 计算缓存
memoization: {
question: '是否缓存昂贵的计算?',
bad: '每次渲染都重新计算',
good: '使用useMemo缓存'
},
// 3. 函数缓存
callbackMemo: {
question: '传给子组件的函数是否缓存?',
bad: '内联函数或每次创建新函数',
good: '使用useCallback缓存'
},
// 4. 组件缓存
componentMemo: {
question: '渲染成本高的组件是否使用memo?',
bad: '普通组件',
good: '使用React.memo'
},
// 5. 列表渲染
listRendering: {
question: '列表是否使用正确的key?',
bad: '使用index作为key',
good: '使用唯一稳定的id'
},
// 6. 条件渲染
conditionalRendering: {
question: '是否避免不必要的渲染?',
bad: '渲染后再隐藏',
good: '条件渲染或懒加载'
}
};4.2 性能审计工具
jsx
function PerformanceAudit() {
const [issues, setIssues] = useState([]);
const checkComponent = (component) => {
const newIssues = [];
// 检查1:是否有大列表没有使用memo
if (component.hasLargeList && !component.usesM么) {
newIssues.push({
severity: 'high',
message: '大列表未使用React.memo优化'
});
}
// 检查2:是否有内联函数传给子组件
if (component.hasInlineFunctions) {
newIssues.push({
severity: 'medium',
message: '使用内联函数,考虑useCallback'
});
}
// 检查3:是否有昂贵的计算没有缓存
if (component.hasExpensiveCalculation && !component.usesMemo) {
newIssues.push({
severity: 'high',
message: '昂贵的计算未使用useMemo缓存'
});
}
setIssues(newIssues);
};
return (
<div>
<h2>性能审计报告</h2>
<ul>
{issues.map((issue, i) => (
<li key={i} className={`issue-${issue.severity}`}>
[{issue.severity}] {issue.message}
</li>
))}
</ul>
</div>
);
}第五部分:优化前后对比数据
5.1 渲染次数对比
jsx
function RenderCountComparison() {
const [count, setCount] = useState(0);
const [items] = useState(Array(100).fill(0).map((_, i) => ({
id: i,
name: `Item ${i}`
})));
// 记录渲染次数
const unoptimizedCount = useRef(0);
const optimizedCount = useRef(0);
const handleClick = useCallback(() => {
console.log('点击');
}, []);
return (
<div>
<button onClick={() => setCount(c => c + 1)}>
更新: {count}
</button>
<div style={{ display: 'flex', gap: '20px' }}>
<div>
<h3>未优化版本</h3>
<p>渲染次数: {unoptimizedCount.current}</p>
{items.map(item => (
<UnoptimizedItem
key={item.id}
item={item}
onClick={handleClick}
renderCount={unoptimizedCount}
/>
))}
</div>
<div>
<h3>优化版本</h3>
<p>渲染次数: {optimizedCount.current}</p>
{items.map(item => (
<OptimizedItem
key={item.id}
item={item}
onClick={handleClick}
renderCount={optimizedCount}
/>
))}
</div>
</div>
</div>
);
}
function UnoptimizedItem({ item, onClick, renderCount }) {
renderCount.current++;
return (
<div onClick={() => onClick(item.id)}>
{item.name}
</div>
);
}
const OptimizedItem = React.memo(function OptimizedItem({ item, onClick, renderCount }) {
renderCount.current++;
return (
<div onClick={() => onClick(item.id)}>
{item.name}
</div>
);
});5.2 内存使用对比
jsx
function MemoryComparison() {
const [showDemo, setShowDemo] = useState(false);
useEffect(() => {
if (showDemo && performance.memory) {
console.log('内存使用:', {
usedJSHeapSize: (performance.memory.usedJSHeapSize / 1048576).toFixed(2) + 'MB',
totalJSHeapSize: (performance.memory.totalJSHeapSize / 1048576).toFixed(2) + 'MB',
jsHeapSizeLimit: (performance.memory.jsHeapSizeLimit / 1048576).toFixed(2) + 'MB'
});
}
}, [showDemo]);
return (
<div>
<button onClick={() => setShowDemo(!showDemo)}>
切换演示
</button>
{showDemo && <HeavyComponent />}
</div>
);
}第六部分:React 19自动优化
6.1 React Compiler
jsx
// React 19编译器自动优化
function AutoOptimizedByCompiler({ items }) {
// 编译器会自动识别并优化这些模式
// 自动添加useMemo
const filtered = items.filter(item => item.active);
// 自动添加useCallback
const handleClick = () => {
console.log('click');
};
// 自动添加React.memo
return (
<div>
{filtered.map(item => (
<Item key={item.id} item={item} onClick={handleClick} />
))}
</div>
);
}
// 编译后可能变成:
function CompiledVersion({ items }) {
const filtered = useMemo(() =>
items.filter(item => item.active),
[items]
);
const handleClick = useCallback(() => {
console.log('click');
}, []);
return (
<div>
{filtered.map(item => (
<MemoItem key={item.id} item={item} onClick={handleClick} />
))}
</div>
);
}
const MemoItem = React.memo(Item);6.2 编译器优化指南
jsx
// 编译器友好的代码模式
function CompilerFriendly() {
// ✅ 好:清晰的数据流
const data = props.data;
const filtered = data.filter(x => x.active);
const mapped = filtered.map(x => x.value);
// ❌ 避免:复杂的嵌套逻辑
const complex = props.data
.filter(x => x.active && someCondition(x))
.map(x => {
if (x.type === 'A') return transformA(x);
if (x.type === 'B') return transformB(x);
return x;
});
}第七部分:最佳实践总结
7.1 优化决策树
jsx
// 决策树:是否需要优化?
function shouldOptimize(component) {
// 1. 组件是否渲染频繁?
if (!component.rendersFrequently) {
return false; // 不需要优化
}
// 2. 组件渲染成本是否高?
if (!component.isExpensiveToRender) {
return false; // 不需要优化
}
// 3. Props是否经常相同?
if (!component.propsOftenSame) {
return false; // memo无效,不需要
}
// 满足以上条件,值得优化
return true;
}
// 应用示例
function OptimizationExample() {
// 场景1:高频更新的简单组件 - 不需要优化
function Clock() {
const [time, setTime] = useState(Date.now());
useEffect(() => {
const timer = setInterval(() => setTime(Date.now()), 1000);
return () => clearInterval(timer);
}, []);
return <div>{new Date(time).toLocaleTimeString()}</div>;
}
// 场景2:低频更新的复杂组件 - 不需要优化
function RarelyUpdated({ data }) {
// 一天才更新一次
return <ComplexChart data={data} />;
}
// 场景3:高频更新、高成本、props稳定 - 需要优化
const OptimizedListItem = React.memo(function ListItem({ item, onAction }) {
// 复杂的渲染逻辑
return <ExpensiveView item={item} onAction={onAction} />;
});
}7.2 优化优先级
jsx
// 优化优先级(从高到低)
const OptimizationPriorities = [
{
priority: 1,
name: '避免不必要的State',
example: '使用派生状态代替重复State'
},
{
priority: 2,
name: '正确使用key',
example: '使用稳定唯一的key'
},
{
priority: 3,
name: '组件懒加载',
example: '使用React.lazy和Suspense'
},
{
priority: 4,
name: '虚拟化长列表',
example: '使用react-window'
},
{
priority: 5,
name: '使用memo系列Hook',
example: 'useMemo, useCallback, React.memo'
}
];练习题
基础练习
- 对比一个列表组件优化前后的渲染次数
- 使用Profiler测量组件渲染时间
- 找出一个组件的性能瓶颈并优化
进阶练习
- 优化一个包含500个项目的商品列表
- 实现一个性能监控组件,显示实时渲染统计
- 创建一个性能对比工具,对比优化前后的差异
高级练习
- 优化一个复杂的数据仪表板应用
- 实现一个聊天应用,支持1000+条消息的高性能渲染
- 分析React 19编译器的优化效果
通过本章学习,你已经全面掌握了React性能优化的各种技术。合理使用这些优化手段,可以让你的应用运行如飞!记住:不要过早优化,先测量再优化。继续学习,成为React性能大师!