React 18.x 完整学习计划
📚 学习计划概览
总时长:12-16周
每周学习时间:15-20小时
适合人群:有JavaScript基础的前端开发者
第一阶段:JavaScript基础巩固 (2周)
学习目标
- 掌握ES6+核心语法
- 理解模块化开发
- 熟悉异步编程
学习内容
第1周:ES6+语法
Day 1-2: 变量声明和作用域
// let/const vs var
let name = 'React';
const version = '18.x';
// 块级作用域
{
let blockScoped = '只在块内有效';
const alsoBlockScoped = '常量';
}
Day 3-4: 箭头函数和解构
// 箭头函数
const add = (a, b) => a + b;
const greet = name => `Hello, ${name}`;
// 解构赋值
const user = { name: 'John', age: 30 };
const { name, age } = user;
const [first, second] = [1, 2, 3];
Day 5-7: 模板字符串和模块化
// 模板字符串
const message = `Hello ${name}, you are ${age} years old`;
// 模块化
// math.js
export const add = (a, b) => a + b;
export default class Calculator { }
// main.js
import Calculator, { add } from './math.js';
第2周:异步编程
Day 1-3: Promise和async/await
// Promise
const fetchData = () => {
return fetch('/api/data')
.then(response => response.json())
.catch(error => console.error(error));
};
// async/await
const fetchDataAsync = async () => {
try {
const response = await fetch('/api/data');
const data = await response.json();
return data;
} catch (error) {
console.error(error);
}
};
Day 4-7: 实践项目
- 构建一个简单的天气查询应用
- 使用fetch API获取数据
- 处理异步错误
实践项目:天气查询应用
// weather.js
class WeatherApp {
constructor() {
this.apiKey = 'your-api-key';
}
async getWeather(city) {
try {
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${this.apiKey}`
);
return await response.json();
} catch (error) {
throw new Error('Failed to fetch weather data');
}
}
}
⚛️ 第二阶段:React基础概念 (2周)
学习目标
- 理解React核心概念
- 掌握JSX语法
- 学会组件开发
学习内容
第1周:React基础
Day 1-2: 环境搭建和第一个组件
# 创建React项目
npx create-react-app my-react-app
cd my-react-app
npm start
// src/App.js
import React from 'react';
function App() {
return (
<div className="App">
<h1>Hello React!</h1>
</div>
);
}
export default App;
Day 3-4: JSX语法深入
// JSX表达式
const name = 'React';
const element = <h1>Hello, {name}</h1>;
// 条件渲染
const isLoggedIn = true;
const greeting = isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please log in.</h1>;
// 列表渲染
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map(number =>
<li key={number}>{number}</li>
);
Day 5-7: 组件和Props
// 函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// 类组件
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
// 使用组件
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div>
);
}
第2周:State和事件处理
Day 1-3: State管理
// 函数组件使用useState
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Day 4-5: 事件处理
// 事件处理
function Button() {
const handleClick = (e) => {
e.preventDefault();
console.log('Button clicked');
};
return <button onClick={handleClick}>Click me</button>;
}
// 表单处理
function Form() {
const [value, setValue] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
console.log('Submitted:', value);
};
return (
<form onSubmit={handleSubmit}>
<input
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<button type="submit">Submit</button>
</form>
);
}
Day 6-7: 实践项目
- 构建一个待办事项应用
- 实现添加、删除、编辑功能
实践项目:待办事项应用
// src/TodoApp.js
import React, { useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
const addTodo = () => {
if (inputValue.trim()) {
setTodos([...todos, {
id: Date.now(),
text: inputValue,
completed: false
}]);
setInputValue('');
}
};
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div>
<h1>Todo App</h1>
<div>
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Add a todo"
/>
<button onClick={addTodo}>Add</button>
</div>
<ul>
{todos.map(todo => (
<li key={todo.id}>
<span
style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}
onClick={() => toggleTodo(todo.id)}
>
{todo.text}
</span>
<button onClick={() => deleteTodo(todo.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default TodoApp;
第三阶段:Hooks深入理解 (2周)
学习目标
- 掌握所有内置Hooks
- 理解Hooks规则
- 学会自定义Hooks
学习内容
第1周:基础Hooks
Day 1-2: useState深入
// 函数式更新
const [count, setCount] = useState(0);
const increment = () => setCount(prevCount => prevCount + 1);
// 对象状态
const [user, setUser] = useState({ name: '', email: '' });
const updateUser = (field, value) => {
setUser(prevUser => ({ ...prevUser, [field]: value }));
};
Day 3-4: useEffect
// 基础用法
useEffect(() => {
document.title = `Count: ${count}`;
});
// 依赖数组
useEffect(() => {
fetchData();
}, [userId]); // 只在userId变化时执行
// 清理函数
useEffect(() => {
const timer = setInterval(() => {
setCount(c => c + 1);
}, 1000);
return () => clearInterval(timer);
}, []);
Day 5-7: useContext
// 创建Context
const ThemeContext = React.createContext();
// Provider组件
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
// 使用Context
function ThemedButton() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<button
style={{ background: theme === 'light' ? '#fff' : '#333' }}
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
>
Toggle Theme
</button>
);
}
第2周:高级Hooks
Day 1-2: useReducer
// Reducer函数
const todoReducer = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return [...state, { id: Date.now(), text: action.text, completed: false }];
case 'TOGGLE_TODO':
return state.map(todo =>
todo.id === action.id ? { ...todo, completed: !todo.completed } : todo
);
case 'DELETE_TODO':
return state.filter(todo => todo.id !== action.id);
default:
return state;
}
};
// 使用useReducer
function TodoApp() {
const [todos, dispatch] = useReducer(todoReducer, []);
const addTodo = (text) => {
dispatch({ type: 'ADD_TODO', text });
};
return (
// JSX...
);
}
Day 3-4: useMemo和useCallback
// useMemo - 记忆化计算结果
const expensiveValue = useMemo(() => {
return heavyCalculation(data);
}, [data]);
// useCallback - 记忆化函数
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
// 避免不必要的重新渲染
const MemoizedComponent = React.memo(({ data }) => {
return <div>{data.name}</div>;
});
Day 5-7: 自定义Hooks
// 自定义Hook: useCounter
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
const increment = useCallback(() => setCount(c => c + 1), []);
const decrement = useCallback(() => setCount(c => c - 1), []);
const reset = useCallback(() => setCount(initialValue), [initialValue]);
return { count, increment, decrement, reset };
}
// 自定义Hook: useFetch
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
实践项目:个人博客系统
// src/hooks/usePosts.js
function usePosts() {
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(false);
const addPost = useCallback((newPost) => {
setPosts(prev => [...prev, { ...newPost, id: Date.now() }]);
}, []);
const deletePost = useCallback((id) => {
setPosts(prev => prev.filter(post => post.id !== id));
}, []);
return { posts, loading, addPost, deletePost };
}
// src/components/BlogApp.js
function BlogApp() {
const { posts, addPost, deletePost } = usePosts();
const [newPost, setNewPost] = useState({ title: '', content: '' });
const handleSubmit = (e) => {
e.preventDefault();
addPost(newPost);
setNewPost({ title: '', content: '' });
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
value={newPost.title}
onChange={(e) => setNewPost({...newPost, title: e.target.value})}
placeholder="Post title"
/>
<textarea
value={newPost.content}
onChange={(e) => setNewPost({...newPost, content: e.target.value})}
placeholder="Post content"
/>
<button type="submit">Add Post</button>
</form>
<div>
{posts.map(post => (
<article key={post.id}>
<h3>{post.title}</h3>
<p>{post.content}</p>
<button onClick={() => deletePost(post.id)}>Delete</button>
</article>
))}
</div>
</div>
);
}
🗂️ 第四阶段:状态管理 (2周)
学习目标
- 理解状态管理概念
- 掌握Redux Toolkit
- 学会Context + useReducer模式
学习内容
第1周:Context + useReducer模式
Day 1-3: 全局状态管理
// src/context/AppContext.js
const AppContext = createContext();
function AppProvider({ children }) {
const [state, dispatch] = useReducer(appReducer, initialState);
return (
<AppContext.Provider value={{ state, dispatch }}>
{children}
</AppContext.Provider>
);
}
// src/reducers/appReducer.js
const initialState = {
user: null,
posts: [],
loading: false,
error: null
};
function appReducer(state, action) {
switch (action.type) {
case 'SET_USER':
return { ...state, user: action.payload };
case 'SET_POSTS':
return { ...state, posts: action.payload };
case 'SET_LOADING':
return { ...state, loading: action.payload };
case 'SET_ERROR':
return { ...state, error: action.payload };
default:
return state;
}
}
Day 4-7: 实践项目
- 构建一个购物车应用
- 使用Context管理全局状态
第2周:Redux Toolkit
Day 1-3: Redux基础
npm install @reduxjs/toolkit react-redux
// src/store/store.js
import { configureStore } from '@reduxjs/toolkit';
import postsReducer from './slices/postsSlice';
export const store = configureStore({
reducer: {
posts: postsReducer,
},
});
// src/store/slices/postsSlice.js
import { createSlice } from '@reduxjs/toolkit';
const postsSlice = createSlice({
name: 'posts',
initialState: {
items: [],
loading: false,
error: null
},
reducers: {
setPosts: (state, action) => {
state.items = action.payload;
},
setLoading: (state, action) => {
state.loading = action.payload;
},
setError: (state, action) => {
state.error = action.payload;
},
addPost: (state, action) => {
state.items.push(action.payload);
}
}
});
export const { setPosts, setLoading, setError, addPost } = postsSlice.actions;
export default postsSlice.reducer;
Day 4-7: 异步操作
// src/store/slices/postsSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
// 异步thunk
export const fetchPosts = createAsyncThunk(
'posts/fetchPosts',
async (_, { rejectWithValue }) => {
try {
const response = await fetch('/api/posts');
if (!response.ok) throw new Error('Failed to fetch posts');
return await response.json();
} catch (error) {
return rejectWithValue(error.message);
}
}
);
const postsSlice = createSlice({
name: 'posts',
initialState: {
items: [],
loading: false,
error: null
},
reducers: {
// 同步reducers...
},
extraReducers: (builder) => {
builder
.addCase(fetchPosts.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchPosts.fulfilled, (state, action) => {
state.loading = false;
state.items = action.payload;
})
.addCase(fetchPosts.rejected, (state, action) => {
state.loading = false;
state.error = action.payload;
});
}
});
实践项目:电商购物车
// src/components/Cart.js
import { useSelector, useDispatch } from 'react-redux';
import { removeItem, updateQuantity } from '../store/slices/cartSlice';
function Cart() {
const { items, total } = useSelector(state => state.cart);
const dispatch = useDispatch();
const handleRemoveItem = (id) => {
dispatch(removeItem(id));
};
const handleUpdateQuantity = (id, quantity) => {
dispatch(updateQuantity({ id, quantity }));
};
return (
<div>
<h2>Shopping Cart</h2>
{items.map(item => (
<div key={item.id}>
<h3>{item.name}</h3>
<p>Price: ${item.price}</p>
<input
type="number"
value={item.quantity}
onChange={(e) => handleUpdateQuantity(item.id, parseInt(e.target.value))}
/>
<button onClick={() => handleRemoveItem(item.id)}>Remove</button>
</div>
))}
<h3>Total: ${total}</h3>
</div>
);
}
🛣️ 第五阶段:路由和导航 (1.5周)
学习目标
- 掌握React Router
- 理解路由守卫
- 学会代码分割
学习内容
第1周:React Router基础
Day 1-3: 基础路由
npm install react-router-dom
// src/App.js
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</BrowserRouter>
);
}
Day 4-7: 动态路由和嵌套路由
// 动态路由
<Route path="/user/:id" element={<UserProfile />} />
// 在组件中获取参数
import { useParams } from 'react-router-dom';
function UserProfile() {
const { id } = useParams();
return <div>User ID: {id}</div>;
}
// 嵌套路由
<Route path="/dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
第2周:高级路由特性
Day 1-3: 路由守卫和权限控制
// 受保护的路由组件
function ProtectedRoute({ children }) {
const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
return children;
}
// 使用受保护的路由
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>
Day 4-7: 代码分割和懒加载
// 懒加载组件
const LazyComponent = React.lazy(() => import('./LazyComponent'));
// 使用Suspense
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
实践项目:多页面博客系统
// src/pages/BlogPost.js
import { useParams, useNavigate } from 'react-router-dom';
function BlogPost() {
const { id } = useParams();
const navigate = useNavigate();
const [post, setPost] = useState(null);
useEffect(() => {
fetchPost(id).then(setPost);
}, [id]);
if (!post) return <div>Loading...</div>;
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
<button onClick={() => navigate('/blog')}>
Back to Blog
</button>
</article>
);
}
⚡ 第六阶段:性能优化 (1.5周)
学习目标
- 理解React性能优化原理
- 掌握优化技巧
- 学会性能分析工具
学习内容
第1周:基础优化
Day 1-3: 组件优化
// React.memo - 防止不必要的重新渲染
const ExpensiveComponent = React.memo(({ data }) => {
return <div>{data.name}</div>;
});
// useMemo - 记忆化计算结果
function ExpensiveCalculation({ items }) {
const expensiveValue = useMemo(() => {
return items.reduce((sum, item) => sum + item.value, 0);
}, [items]);
return <div>Total: {expensiveValue}</div>;
}
// useCallback - 记忆化函数
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
console.log('Button clicked');
}, []);
return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<ChildComponent onClick={handleClick} />
</div>
);
}
Day 4-7: 列表优化
// 虚拟滚动
import { FixedSizeList as List } from 'react-window';
function VirtualizedList({ items }) {
const Row = ({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
);
return (
<List
height={600}
itemCount={items.length}
itemSize={50}
>
{Row}
</List>
);
}
第2周:高级优化
Day 1-3: 代码分割
// 路由级别的代码分割
const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));
// 组件级别的代码分割
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
);
}
Day 4-7: 性能分析工具
// React DevTools Profiler
// 使用Profiler组件
function ProfiledComponent() {
return (
<Profiler id="MyComponent" onRender={onRenderCallback}>
<MyComponent />
</Profiler>
);
}
function onRenderCallback(id, phase, actualDuration) {
console.log('Component:', id, 'Phase:', phase, 'Duration:', actualDuration);
}
实践项目:高性能数据表格
// src/components/DataTable.js
import { memo, useMemo } from 'react';
import { FixedSizeList as List } from 'react-window';
const DataTable = memo(({ data, columns }) => {
const Row = memo(({ index, style }) => {
const item = data[index];
return (
<div style={style} className="table-row">
{columns.map(column => (
<div key={column.key} className="table-cell">
{column.render ? column.render(item[column.key], item) : item[column.key]}
</div>
))}
</div>
);
});
return (
<List
height={600}
itemCount={data.length}
itemSize={50}
width="100%"
>
{Row}
</List>
);
});
🧪 第七阶段:测试 (1.5周)
学习目标
- 掌握React Testing Library
- 理解测试最佳实践
- 学会测试驱动开发
学习内容
第1周:基础测试
Day 1-3: 组件测试
npm install --save-dev @testing-library/react @testing-library/jest-dom
// src/components/__tests__/Button.test.js
import { render, screen, fireEvent } from '@testing-library/react';
import Button from '../Button';
test('renders button with text', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
test('calls onClick when clicked', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByText('Click me'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
Day 4-7: Hooks测试
// src/hooks/__tests__/useCounter.test.js
import { renderHook, act } from '@testing-library/react';
import { useCounter } from '../useCounter';
test('should increment counter', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
第2周:集成测试
Day 1-3: 用户交互测试
// src/components/__tests__/TodoApp.test.js
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import TodoApp from '../TodoApp';
test('adds new todo', async () => {
render(<TodoApp />);
const input = screen.getByPlaceholderText('Add a todo');
const addButton = screen.getByText('Add');
fireEvent.change(input, { target: { value: 'New todo' } });
fireEvent.click(addButton);
await waitFor(() => {
expect(screen.getByText('New todo')).toBeInTheDocument();
});
});
Day 4-7: 异步操作测试
// src/components/__tests__/DataFetcher.test.js
import { render, screen, waitFor } from '@testing-library/react';
import DataFetcher from '../DataFetcher';
// Mock fetch
global.fetch = jest.fn();
test('displays data after fetch', async () => {
const mockData = { name: 'Test User' };
fetch.mockResolvedValueOnce({
ok: true,
json: async () => mockData,
});
render(<DataFetcher />);
await waitFor(() => {
expect(screen.getByText('Test User')).toBeInTheDocument();
});
});
实践项目:测试完整的待办事项应用
// src/components/__tests__/TodoApp.integration.test.js
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { store } from '../store';
import TodoApp from '../TodoApp';
const renderWithProvider = (component) => {
return render(
<Provider store={store}>
{component}
</Provider>
);
};
test('complete todo workflow', async () => {
renderWithProvider(<TodoApp />);
// Add todo
const input = screen.getByPlaceholderText('Add a todo');
fireEvent.change(input, { target: { value: 'Test todo' } });
fireEvent.click(screen.getByText('Add'));
// Verify todo is added
await waitFor(() => {
expect(screen.getByText('Test todo')).toBeInTheDocument();
});
// Toggle todo
fireEvent.click(screen.getByText('Test todo'));
expect(screen.getByText('Test todo')).toHaveStyle('text-decoration: line-through');
// Delete todo
fireEvent.click(screen.getByText('Delete'));
await waitFor(() => {
expect(screen.queryByText('Test todo')).not.toBeInTheDocument();
});
});
🚀 第八阶段:高级特性和最佳实践 (2周)
学习目标
- 掌握React 18新特性
- 理解并发特性
- 学会最佳实践
学习内容
第1周:React 18新特性
Day 1-3: 并发特性
// useTransition - 非阻塞更新
import { useTransition, useState } from 'react';
function SearchResults() {
const [isPending, startTransition] = useTransition();
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const handleSearch = (newQuery) => {
setQuery(newQuery);
startTransition(() => {
// 这个更新可以被中断
setResults(expensiveSearch(newQuery));
});
};
return (
<div>
<input
value={query}
onChange={(e) => handleSearch(e.target.value)}
/>
{isPending && <div>Searching...</div>}
<div>{results.map(result => <div key={result.id}>{result.title}</div>)}</div>
</div>
);
}
// useDeferredValue - 延迟更新
import { useDeferredValue } from 'react';
function ProductList({ products }) {
const deferredProducts = useDeferredValue(products);
return (
<div>
{deferredProducts.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
Day 4-7: Suspense改进
// 服务端渲染支持
import { Suspense } from 'react';
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
);
}
// 错误边界
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
第2周:最佳实践和项目架构
Day 1-3: 项目结构
src/
├── components/ # 可复用组件
│ ├── ui/ # 基础UI组件
│ └── features/ # 功能组件
├── pages/ # 页面组件
├── hooks/ # 自定义Hooks
├── store/ # 状态管理
├── services/ # API服务
├── utils/ # 工具函数
├── types/ # TypeScript类型
└── tests/ # 测试文件
Day 4-7: 性能监控和优化
// 性能监控
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
// 发送性能数据到分析服务
console.log(metric);
}
getCLS(sendToAnalytics);
getFID(sendToAnalytics);
getFCP(sendToAnalytics);
getLCP(sendToAnalytics);
getTTFB(sendToAnalytics);
// 懒加载和预加载
const LazyComponent = lazy(() =>
import('./LazyComponent').then(module => ({
default: module.LazyComponent
}))
);
// 预加载
const preloadComponent = () => {
import('./LazyComponent');
};
最终项目:完整的全栈应用
// src/App.js - 完整的应用架构
import React, { Suspense } from 'react';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import { store } from './store';
import { ErrorBoundary } from './components/ErrorBoundary';
import { ThemeProvider } from './context/ThemeContext';
import Routes from './Routes';
function App() {
return (
<ErrorBoundary>
<Provider store={store}>
<ThemeProvider>
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes />
</Suspense>
</BrowserRouter>
</ThemeProvider>
</Provider>
</ErrorBoundary>
);
}
export default App;
📚 学习资源推荐
官方文档
在线课程
实践平台
工具和库
- 开发工具: Create React App, Vite, Next.js
- 状态管理: Redux Toolkit, Zustand, Jotai
- 路由: React Router
- 测试: Jest, React Testing Library, Cypress
- 样式: Styled Components, Emotion, Tailwind CSS
学习检查点
每周检查点
- 第2周: 能独立构建基础组件
- 第4周: 掌握Hooks并能自定义Hook
- 第6周: 能使用状态管理构建复杂应用
- 第8周: 掌握路由和导航
- 第10周: 能进行性能优化
- 第12周: 能编写测试用例
- 第14周: 掌握React 18新特性
- 第16周: 能构建完整的全栈应用
最终目标
- 能够独立开发React应用
- 理解React生态系统
- 掌握最佳实践
- 具备解决复杂问题的能力
这个学习计划将帮助你从React初学者成长为能够独立开发复杂应用的React开发者。记住,学习编程最重要的是多实践,多写代码!
[1 tool called]
我已经为你制定了一个完整的React 18.x学习计划!这个计划包含8个阶段,总共12-16周的学习时间,每个阶段都有详细的学习内容、实践项目和检查点。
学习计划亮点:
- 循序渐进:从JavaScript基础到React高级特性
- 实践导向:每个阶段都有具体的实践项目
- 全面覆盖:包含Hooks、状态管理、路由、性能优化、测试等
- 现代化:重点学习React 18的新特性和最佳实践
- 可衡量:每个阶段都有明确的学习目标和检查点
建议的学习方式:
- 每天学习2-3小时,保持连续性
- 多动手实践,不要只看理论
- 遇到问题及时查阅文档和社区资源
- 定期回顾和总结学习内容
可以根据自己的时间安排调整学习进度,但建议不要跳过任何阶段,因为每个阶段都是后续学习的基础。
更多推荐


所有评论(0)