React JSX 语法规则详解与实战指南
一、引言:为什么需要 JSX?
JSX 是 React 的核心语法,它允许我们在 JavaScript 中编写类似 HTML 的结构。与传统的字符串拼接相比,JSX 提供了更直观、更高效的组件化开发方式。本文将从基础语法到实际应用,带你全面掌握 JSX 的规则与技巧。
二、JSX 基础语法规则
1. 基本结构
// 正确写法
const element = <div>Hello, World!</div>;
// 错误写法(缺少 RXH 包裹)
const element = div("Hello, World!");
核心规则:
- 必须用
<>包裹内容 - 标签名必须是小写(HTML 标签)或首字母大写(自定义组件)
- 必须闭合所有标签
2. 嵌套与自闭合标签
// 嵌套结构
const nested = (
<div>
<h1>标题</h1>
<p>段落内容</p >
</div>
);
// 自闭合标签
const selfClosed = < img src="logo.png" alt="Logo" />;
注意:
- 自闭合标签必须带
/ - 多个同级元素需用
<>...</>包裹(Fragment)
3. 表达式与注释
// 插入表达式
const name = "Alice";
const greeting = <h1>Hello, {name}!</h1>;
{/* JSX 注释 */}
const comment = (
<div>
内容 {/* 这里是注释 */}
</div>
);
规则:
{}中必须是合法的 JavaScript 表达式- HTML 注释在 JSX 中会报错,需用
{/* */}格式
三、动态内容与事件处理
1. 动态属性与样式
// 动态样式
const isActive = true;
const button = (
<button style={{ color: isActive ? 'white' : 'black', backgroundColor: isActive ? 'blue' : 'gray' }}>
Click Me
</button>
);
// 动态类名(推荐方式)
const className = isActive ? 'active' : 'inactive';
const dynamicClass = <div className={className}>Content</div>;
最佳实践:
- 避免直接写内联样式对象,推荐使用 CSS Modules 或 Styled Components
- 类名拼接推荐使用
classnames库
2. 事件绑定
// 基础事件绑定
function handleClick() {
alert('Button clicked!');
}
const button = <button onClick={handleClick}>Click</button>;
// 传递参数
const id = 123;
const actionButton = <button onClick={() => handleAction(id)}>Action</button>;
关键点:
- 事件处理函数必须通过
onXXX属性绑定 - JSX 中不能直接调用函数,需用事件触发
四、条件渲染与列表渲染
1. 条件渲染
// 三元运算符
const show = true;
const conditional = show ? <div>Visible</div> : null;
// 短路运算符
const shortCircuit = show && <div>Short Circuit</div>;
// 立即执行函数(推荐)
const immediate = (
<>
{show && <div>Rendered with IIFE</div>}
</>
);
2. 列表渲染
// 基础列表
const items = ['Apple', 'Banana', 'Cherry'];
const list = (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
// 带复杂结构的列表
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const userList = (
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{users.map(user => (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.name}</td>
</tr>
))}
</tbody>
</table>
);
关键规则:
- 必须有
key属性(推荐唯一 ID) - 避免在循环中直接返回数组,需用
<>...</>包裹
五、样式与布局控制
1. 内联样式
const inlineStyle = <div style={{ textAlign: 'center', padding: '20px' }}>
Centered Content
</div>;
注意事项:
- 样式对象需使用 camelCase(如
fontSize而非font-size) - 优先使用 CSS 类,内联样式仅用于动态场景
2. CSS 模块化
import styles from './Component.module.css';
const modularCss = (
<div className={styles.container}>
<h2 className={styles['title-large']}>Modular CSS</h2>
</div>
);
六、组件组合与复用
1. 函数组件与 Class 组件
// 函数组件
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
// Class 组件
class Counter extends React.Component {
state = { count: 0 };
render() {
return (
<div>
<p>Count: {this.state.count}</p >
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Increment
</button>
</div>
);
}
}
2. 组件嵌套
function App() {
return (
<div>
<Greeting name="Alice" />
<Counter />
</div>
);
}
规则:
- 组件首字母必须大写
- 组件之间可嵌套任意层级
七、Hooks 与 JSX 结合
1. 使用 useState
function TodoApp() {
const [todos, setTodos] = React.useState(['Buy milk']);
const [newTodo, setNewTodo] = React.useState('');
const addTodo = () => {
setTodos([...todos, newTodo]);
setNewTodo('');
};
return (
<div>
<input
type="text"
value={newTodo}
onChange={e => setNewTodo(e.target.value)}
/>
<button onClick={addTodo}>Add</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
}
2. 使用 useEffect
function Clock() {
const [time, setTime] = React.useState(new Date().toLocaleTimeString());
React.useEffect(() => {
const timer = setInterval(() => {
setTime(new Date().toLocaleTimeString());
}, 1000);
return () => clearInterval(timer); // 清理副作用
}, []);
return <h2>Current Time: {time}</h2>;
}
八、性能优化与最佳实践
1. 虚拟 DOM 原理
// 对比直接 DOM 操作
// 不推荐:频繁操作真实 DOM
function updateDOM() {
const dom = document.getElementById('root');
dom.innerHTML = 'New Content';
}
// 推荐:使用 React 更新虚拟 DOM
function updateReact() {
ReactDOM.render(<div>New Content</div>, root);
}
2. 列表渲染优化
// 错误用法(可能导致不必要的重渲)
{items.map((item, index) => (
<Item key={index} data={item} />
))}
// 正确用法(使用稳定 key)
{items.map(item => (
<Item key={item.id} data={item} />
))}
核心原则:
- 保证
key的唯一性 - 避免使用数组索引作为 key(除非列表不会重新排序)
九、总结与实战建议
- 保持简洁:避免过度嵌套,适当使用 Fragment 或第三方库(如 react-fragment)
- 类型安全:结合 TypeScript 使用 JSX,获得更好的开发体验
- 性能优先:合理使用
memo、useCallback等优化手段 - 规范统一:团队约定 JSX 书写风格(如空格、缩进、引号)
十、完整实战示例:待办事项应用
// App.js
import React, { useState } from 'react';
import TodoList from './TodoList';
import TodoInput from './TodoInput';
function App() {
const [todos, setTodos] = useState([]);
const [filter, setFilter] = useState('all');
const addTodo = (text) => {
setTodos([...todos, { id: Date.now(), text }]);
};
const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};
return (
<div className="app">
<h1>Todo App</h1>
<TodoInput onAdd={addTodo} />
<div>
<button onClick={() => setFilter('all')}>All</button>
<button onClick={() => setFilter('active')}>Active</button>
<button onClick={() => setFilter('completed')}>Completed</button>
</div>
<TodoList todos={todos} filter={filter} onDelete={deleteTodo} />
</div>
);
}
export default App;
// TodoList.js
import React from 'react';
function TodoList({ todos, filter, onDelete }) {
const filtered = todos.filter(todo => {
if (filter === 'all') return true;
if (filter === 'active') return !todo.completed;
if (filter === 'completed') return todo.completed;
});
return (
<ul>
{filtered.map(todo => (
<li key={todo.id}>
<span
className={todo.completed ? 'completed' : ''}
onClick={() => toggleComplete(todo.id)}
>
{todo.text}
</span>
<button onClick={() => onDelete(todo.id)}>Delete</button>
</li>
))}
</ul>
);
}
export default TodoList;
// TodoInput.js
import React, { useState } from 'react';
function TodoInput({ onAdd }) {
const [text, setText] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (text.trim()) {
onAdd(text);
setText('');
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={text}
onChange={e => setText(e.target.value)}
placeholder="Add a todo..."
/>
<button type="submit">Add</button>
</form>
);
}
export default TodoInput;
运行效果:
- 添加/删除待办事项
- 按状态过滤任务
- 点击任务文本标记完成
通过本文的学习,你应该能够熟练掌握 JSX 的核心语法规则,并在实际项目中灵活应用。记住,JSX 的本质是函数调用,理解这一点将帮助你更好地驾驭 React 开发。