React学习笔记:从JSX到组件化开发
React作为现代前端开发的主流框架之一,以其独特的组件化思想和高效的渲染机制赢得了广泛的应用。React的核心亮点在于JSX语法,它将XML元素直接嵌入JavaScript中,使得开发者能够以声明式方式编写用户界面 。与Vue等其他前端框架相比,React采用更激进的开发方式,入门门槛相对较高,但其强大的生态系统和灵活的架构设计使其成为构建复杂Web应用的理想选择。
一、React概述与现代前端框架定位
React是由Facebook开发并维护的一个专注于构建用户界面的JavaScript库 。它采用组件化开发模式,将用户界面拆分为多个独立的组件,每个组件负责特定功能,通过组合这些组件来构建完整的应用 。React的核心思想是"声明式UI",开发者只需描述界面在给定状态下的样子,React会自动处理界面更新。
在现代前端框架生态中,React占据着重要地位。根据2025年的最新数据,React在企业采用率方面领先于Vue,LinkedIn上React岗位数量是Vue的2.3倍 。React的优势主要体现在以下几个方面:
首先,React拥有强大的设计团队和社区支持。Facebook(现Meta)的前端团队持续维护和更新React,确保其技术领先性和稳定性。React社区活跃度高,GitHub贡献者数量是Vue的2.1倍 ,这意味着开发者可以轻松找到解决方案和最佳实践。
其次,React的生态系统非常丰富。从状态管理(Redux)、路由(React Router)到UI组件库(Ant Design、Material UI)等,React拥有完善的工具链,开发者可以根据项目需求灵活选择和集成这些工具。
第三,React的跨平台能力出色。React Native允许开发者使用相同的React语法构建移动应用,代码复用率可达85%以上 。这种能力使React在全栈和跨平台开发中具有独特优势。
最后,React持续演进,不断引入创新特性。2025年发布的React 19引入了React Compiler、Server Components和新的Hooks(如useOptimistic) ,进一步简化了开发流程并提升了性能。
二、JSX语法详解
JSX(JavaScript XML)是React的核心语法特性,它是一种JavaScript的语法扩展,允许开发者在JavaScript中编写类似XML的元素 。JSX的本质是让开发者能够在JavaScript中直接描述UI结构,从而实现声明式编程 。最终,JSX会被编译为React.createElement()函数调用,创建React元素。
1. JSX基本语法特点
JSX语法与HTML高度相似,但有一些重要区别:
首先,JSX元素是自闭合的。例如,<img />在JSX中是有效的,而在HTML中可能需要写成<img>或<img />。
其次,JSX中使用大括号{}来嵌入动态表达式。例如:
const name = "React";
return <h1>Hello, {name}</h1>;
第三,JSX中使用className代替HTML的class属性,使用htmlFor代替for属性。这是因为class和for是JavaScript的保留关键字。
第四,JSX中可以使用条件表达式和逻辑与操作符。例如:
{isLoggedIn ? <p>欢迎回来!</p> : <p>请登录。</p>}
{isLoggedIn && <button>退出登录</button>}
第五,JSX中可以使用数组展开运算符来渲染多个元素。例如:
const items = ["React", "JSX", "Hooks"];
return <ul>{items.map(item => <li>{item}</li>)}</ul>;
2. JSX编译原理
当编写JSX代码时,实际上是在编写一种扩展的JavaScript语法。在构建过程中,JSX会被编译为React.createElement()函数调用 ,该函数接受三个参数:标签名、属性对象和子元素。
例如,以下JSX代码:
<div id="title">
<span className="title_span">Hello, React</span>
</div>
会被编译为:
React.createElement("div", { id: "title" },
React.createElement("span", { className: "title_span" }, "Hello, React")
);
这种编译过程使得React能够高效地管理虚拟DOM,并通过Diff算法最小化实际DOM操作。
3. JSX与HTML的差异
JSX与HTML虽然语法相似,但在使用上有明显差异:
| 特性 | JSX | HTML |
|---|---|---|
| 类名 | className | class |
| 样式 | 内联样式使用对象 | 使用CSS文件 |
| 属性值 | 表达式用大括号包裹 | 字符串用引号包裹 |
| 自闭合标签 | 必须闭合或使用自闭合语法 | 可以省略闭合标签 |
| 事件处理 | 使用on前缀(如onClick) | 使用原生事件名(如click) |
| 表达式 | 可以使用JavaScript表达式 | 仅限静态内容 |
4. TypeScript中的JSX类型支持
在TypeScript项目中使用JSX时,可以为组件和属性添加类型定义,增强代码的可维护性和安全性 。
interface GreetingProps {
name: string;
enthusiasmLevel?: number;
}
const Greeting: React.FC <GreetingProps> = ({ name, enthusiasmLevel = 1 }) => {
const exclamationMarks = '!'.repeat(enjoymentLevel);
return <h1>{`Hello${name融资exclamationMarks}!`}</h1>;
};
在TypeScript配置文件中,需要设置jsx选项:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}
三、React组件概念、创建方式与组合方法
1. 组件概念与基本结构
React组件是UI的基本构建单元,它接收props作为输入,并返回JSX元素描述界面。组件可以是函数组件或类组件,但自React 16.8引入Hooks以来,函数组件已成为官方推荐的主流创建方式。
一个典型的React组件结构如下:
function JuejinHeader() {
return (
<div>
<header>
<h1>JueJin首页</h1>
</header>
</div>
);
}
2. 函数组件与类组件对比
| 特性 | 函数组件 | 类组件 |
|---|---|---|
| 状态管理 | useState等Hooks | this.state与setState |
| 副作用处理 | useEffect | 组件生命周期方法 |
| 逻辑复用 | 自定义Hooks | 高阶组件或混合模式 |
| 代码简洁性 | 更简洁 | 较复杂,需继承React.Component |
| 性能 | 更优,可记忆化 | 可能有性能开销 |
| 开发体验 | 更好,心智模型简单 | 初学较难,需理解this绑定 |
函数组件通过Hooks提供了更直观的状态管理和副作用处理方式 。例如,使用useEffect可以替代类组件的componentDidMount、componentDidUpdate和componentWillUnmount等生命周期方法 。
// 函数组件示例
function Clock() {
const [date, setDate] = useState(new Date());
useEffect(() => {
const timer = setInterval(() => {
setDate(new Date());
}, 1000);
return () => clearInterval(timer);
}, []);
return <div>当前时间:{date.toString()}</div>;
}
3. 组件组合模式
React组件可以通过多种方式组合,形成复杂的应用界面:
基础组合:通过嵌套和props传递实现父子组件通信 。
function App() {
return (
<div>
<JuejinHeader />
<main>
<Articles />
<aside>
<Checkin />
<Top Articles />
</aside>
</main>
</div>
);
}
高阶组件(HOC):接收组件并返回增强后的新组件,适用于数据注入、权限控制等场景 。
const withAuth = (WrappedComponent) => {
return (props) => {
const isAuthenticated = localStorage.getItem('token');
if (!isAuthenticated) {
return <Redirect to="/login" />;
}
return <裹住的组件 {...props} />;
};
};
const ProtectedDashboard = withAuth(Dashboard);
渲染道具:通过函数prop动态控制渲染内容,实现逻辑复用 。
const MouseTracker = ({ render }) => {
const [pos, setPos] = useState({ x: 0, y: 0 });
return (
<div onMouseMove={(e) => setPos({ x: e.clientX, y: e.clientY })}>
{render(pos)}
</div>
);
};
// 使用示例
<MouseTracker
render={(pos) => <p>鼠标位置:{pos.x}, {pos.y}</p>}
/>
复合组件:组合多个组件形成新功能 。
const InputWithLabel = ({ label, ...props }) => {
return (
<div>
<label>{label}</label>
<input {...props} />
</div>
);
};
4. 组件最佳实践
组件粒度:保持组件小而专注,遵循单一职责原则。
组件命名:使用名词或名词短语,避免动词,保持一致性。
状态提升:将共享状态提升到最近的共同父组件中。
性能优化:使用React.memo避免不必要的渲染,或使用PureComponent进行浅比较。
// 使用React.memo优化性能
const MemoizedCheckin = React.memo(Checkin);
// 或使用PureComponent
class PureCheckin extends React.PureComponent {
// ...
}
四、React状态管理机制与常用Hooks
React的状态管理机制经历了从类组件的this.state到函数组件Hooks的演变。随着React 16.8引入Hooks,函数组件现在能够轻松管理状态和副作用 ,成为构建React应用的首选方式。
1. 基础状态管理Hooks
useState:用于管理组件内部状态 。
function App() {
const [name, setName] = useState('vue');
const [todos, setTodos] = useState([
{
id: 1,
title: '学习React',
done: false,
},
// 其他待办事项...
]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
// 切换登录状态
const toggleLoggedIn = () => {
setIsLoggedIn(!isLoggedIn);
};
return (
<div>
<h1>Hello <span className='title}>{name}</span></h1>
{isLoggedIn ? <div>已登录</div> : <div>未登录</div>}
<button onClick={toggleLoggedIn}>
{isLoggedIn ? '退出登录' : '登录'}
</button>
</div>
);
}
useEffect:用于处理副作用,如数据获取、订阅等 。
useEffect(() => {
// 组件挂载时执行
fetchData();
// 组件卸载时清理
return () => {
cleanup();
};
}, [dependency]); // 依赖数组控制何时重新执行
2. 高级状态管理Hooks
useContext:用于在组件树中共享状态,避免props钻取 。
// 创建Context
const ThemeContext = React.createContext();
// Provider组件
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
< JuejinHeader />
<main>
<Articles />
</main>
</ThemeContext.Provider>
);
}
// 使用Context
function ThemedButton() {
const { theme } = React.useContext(ThemeContext);
return <button className={`button button-${theme}`}>按钮</button>;
}
useReducer:用于管理复杂状态逻辑,通常与Context API结合使用 。
const todoReducer = (state, action) => {
switch (action.type) {
case 'ADDTODO':
return [...state, { id: Date.now(), text: action.text, done: false }];
case 'TOGGLEDONE':
return state.map(todo =>
todo.id === action.id ? { ...todo, done: !todo.done } : todo
);
default:
return state;
}
};
function TodoApp() {
const [todos, dispatch] = useState(todoReducer, []);
// ...
}
3. React 19新增状态管理Hooks
React 19引入了一系列新Hooks,进一步简化了状态管理和副作用处理 :
useOptimistic:用于乐观更新UI,提升用户体验 。
function TodoList({ todos }) {
const [optimisticTodos, addOptimisticTodo] = useOptimistic(
todos,
(state, newTodo) => [...state, { ...newTodo, pending: true }]
);
const addTodo = async (text) => {
const newTodo = { id: Date.now(), text };
addOptimisticTodo(newTodo);
try {
await createTodo(text);
} catch (err) {
// 错误处理
}
};
return (
<ul>
{optimisticTodos.map(todo => (
<li
key={todo.id}
className={todo.pending ? 'pending' :"}
>
{todo.text}
</li>
))}
</ul>
);
}
useFormStatus:与表单操作协同,感知表单状态 。
useFormState:管理表单提交状态和响应 。
这些新Hooks使得React在表单管理和状态同步方面更加简洁高效。
五、完整React应用示例与最佳实践
1. Next.js与React 19构建Todo应用
Next.js是一个基于React的全栈框架,支持服务端渲染(SSR)和静态站点生成(SSG) 。结合React 19的Server Components和新Hooks,可以构建高性能的现代Web应用。
项目结构:
src/
app/
todo/
page.tsx
components/
TodoForm.tsx
TodoList.tsx
TodoItem.tsx
contexts/
TodoContext.tsx
lib/
api.ts
styles/
global.css
服务端组件(TodoList):
// src/app/todo/page.tsx
import TodoForm from './components/TodoForm';
import TodoList from './components/TodoList';
import TodoContextProvider from './contexts/TodoContext';
export default function TodoPage() {
return (
<TodoContextProvider>
<div className="min-h-screen p-8">
<h1 className="text-3xl font-bold mb-8 text-center">Todo List</h1>
<TodoForm />
<TodoList />
</div>
</TodoContextProvider>
);
}
客户端组件(TodoForm):
// src/appTODO/page.tsx
// "use client"; // 表示这是一个客户端组件
import { useState } from 'react';
export default function TodoForm() {
const [inputValue, setInputValue] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
if (inputValue.trim() === '') return;
// 使用useOptimistic实现乐观更新
// ...
// 提交到服务器
// ...
setInputValue('');
};
return (
<form onSubmit={handleSubmit} className="mb-8">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="添加新的待办事项..."
className="px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
type="submit"
className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
添加
</button>
</form>
);
}
状态管理(TodoContext):
// src/appTODO/contexts/TodoContext.tsx
import { createContext, useState, useEffect } from 'react';
export const TodoContext = createContext();
export function TodoContextProvider({ children }) {
const [todos, setTodos] = useState([]);
const [inputValue, setInputValue] = useState('');
// 从服务器获取初始数据
useEffect(() => {
fetch('/api/todos')
.then(res => res.json())
.then(data => setTodos(data));
}, []);
// 添加Todo
const addTodo = async (text) => {
// 乐观更新
// ...
// 提交到服务器
// ...
// 更新状态
// ...
};
// 切换Todo完成状态
const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, done: !todo.done } : todo
));
};
return (
<TodoContext.Provider value={{ todos, addTodo, toggleTodo }}>
{children}
</TodoContext.Provider>
);
}
2. React最佳实践
代码组织:按功能或组件类型组织代码,避免深层嵌套。
性能优化:使用React.memo避免不必要的渲染,使用useMemo缓存计算结果 。
const MemoizedTodoItem = React.memo(TodoItem);
const TodoList = ({ todos }) => {
const optimizedTodos = React.useMemo(() => {
// 复杂计算
return todos;
}, [todos]);
return (
<ul>
{optimizedTodos.map(todo => (
<MemoizedTodoItem key={todo.id} todo={todo} />
))}
</ul>
);
};
错误处理:使用ErrorBoundary捕获组件树中的错误 。
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新状态以显示错误UI
return { hasError: true };
}
render() {
if (this.state.hasError) {
// 显示备用UI
return <h1>发生了错误。</h1>;
}
return this.props.children;
}
}
// 使用ErrorBoundary
<ErrorBoundary>
<TodoList />
</ErrorBoundary>
测试策略:使用Jest和React Testing Library进行单元测试和集成测试。
// TodoForm测试
import { render, screen, fireEvent } from '@testing-library/react';
import TodoForm from './TodoForm';
test('添加Todo', async () => {
render(<TodoForm />);
const input = screen.getByPlaceholderText('添加新的待办事项...');
const button = screen.getByText('添加');
fireEvent change(input, { target: { value: '学习React Hooks' } });
await act(() =>火灾Event click(button));
expect(screen.getByText('学习React Hooks')).toBeInTheDocument();
});
构建优化:使用SWC编译器替代Babel,提升构建性能 。
// vite.config.ts
import react from '@vitejs/plugin-react-swc';
export default defineConfig({
plugins: [
react({
jsxImportSource: '@emotion/react',
tsDecorators: true,
}),
],
});
六、总结与学习路径建议
React作为现代前端开发的主流框架,其核心优势在于组件化开发和高效的渲染机制。JSX语法是React的亮点,它允许开发者在JavaScript中直接描述UI结构,实现声明式编程 。虽然React的入门门槛相对较高,但其强大的生态系统和灵活的架构设计使其成为构建复杂Web应用的理想选择。
对于React学习,建议采取以下路径:
首先,掌握React基础概念和JSX语法,理解组件化思想和虚拟DOM机制。
其次,深入学习React Hooks,特别是useState、useEffect等基础Hooks,以及useContext、useReducer等高级Hooks。
第三,了解React生态中的常用工具,如React Router、Redux、Ant Design等,掌握它们与React的集成方式。
最后,实践构建完整应用,从简单组件开始,逐步构建复杂界面,学习状态管理和性能优化技巧。
通过系统学习和实践,开发者可以充分发挥React的优势,构建高性能、可维护的现代Web应用。React的持续演进和创新特性(如React 19的Server Components和新Hooks)将继续推动前端开发的发展,为开发者提供更简洁高效的状态管理方式。