React JSX 核心语法:从入门到业务开发实战
适合人群:有 JavaScript 基础,正在学习 React 的开发者。
学习目标:快速掌握 JSX 的核心语法,能够阅读 React 组件,并独立编写列表、表单和动态页面。
一、JSX 是什么?
JSX(JavaScript XML)是 JavaScript 的一种语法扩展,允许我们在 JavaScript 中编写类似 HTML 的代码。
例如:
function App() {
return (
<div>
<h1>Hello React</h1>
<p>欢迎学习 JSX</p>
</div>
);
}
JSX 本质上不是 HTML,而是通过 Babel 等工具转换成 JavaScript,生成 React Element(React 元素),最后由 React 渲染到页面。
可以简单理解为:
JSX
↓
编译工具转换
↓
JavaScript(React Element)
↓
React 渲染
↓
真实 DOM
二、JSX 最重要的 8 个知识点
| 知识点 | 优先级 | 实际用途 |
|---|---|---|
| JSX 基本语法 | P0 | 描述页面结构 |
{} 表达式 | P0 | 动态展示数据 |
| 条件渲染 | P0 | 根据状态切换内容 |
列表渲染 map() | P0 | 展示任务列表 |
| 事件绑定 | P0 | 点击、输入、提交 |
| Props 属性传递 | P0 | 组件通信与复用 |
style、className | P0 | 控制元素样式 |
| Fragment、key | P1 | 组件结构与列表更新 |
三、JSX 基本语法
1. 标签必须正确闭合
HTML 中:
<input type="text">
<img src="logo.png">
JSX 中:
<input type="text" />
<img src="logo.png" alt="Logo" />
JSX 要求标签正确闭合。
2. 一个 JSX 表达式只能有一个根节点
错误:
function App() {
return (
<h1>标题</h1>
<p>内容</p>
);
}
正确:
function App() {
return (
<div>
<h1>标题</h1>
<p>内容</p>
</div>
);
}
也可以使用 Fragment:
function App() {
return (
<>
<h1>标题</h1>
<p>内容</p>
</>
);
}
<>...</> 不会额外生成 DOM 元素。
你可以把 JSX 分为两类:
- HTML 标签:例如
<div>、<span>、<h1>,React 会创建对应的真实 DOM 元素。 - Fragment 标签:例如
<>...</>,它只是告诉 React「这些元素属于同一组」,不会创建真实 DOM 容器。
JSX 的一个核心语法规则:为什么 React 组件不能直接返回两个并列的 <div>,非要用 <>...</> 包起来?
其实原因很简单:React 组件的 return 需要返回一个值,而两个并列的 JSX 元素不能直接组成一个合法的 JavaScript 表达式。
3. class 要写成 className
HTML:
<div class="container">Hello</div>
JSX:
<div className="container">Hello</div>
这是最常见的 JSX 语法区别之一。
四、JSX 中的 JavaScript 表达式 {}(重点)
JSX 中的 {} 表示可以在这里嵌入 JavaScript 表达式。
1. 渲染变量
function Task() {
const name = "回查任务";
const count = 10;
return (
<div>
<h2>{name}</h2>
<p>任务数量:{count}</p>
</div>
);
}
2. 执行表达式
const count = 10;
return (
<div>
<p>{count + 1}</p>
<p>{count > 5 ? "任务较多" : "任务较少"}</p>
</div>
);
3. 调用函数
function formatName(name) {
return name.toUpperCase();
}
function App() {
return <h1>{formatName("kevin")}</h1>;
}
页面会显示:
KEVIN
注意:{} 中可以放 JavaScript 表达式,但不能直接写普通的 if、for 语句。
五、条件渲染(重点)
实际开发中,经常需要根据数据状态显示不同的 UI。
1. 三元运算符
function TaskStatus({ status }) {
return (
<span>
{status === "running" ? "运行中" : "已停止"}
</span>
);
}
这里:
条件 ? 结果A : 结果B
表示条件成立显示 A,否则显示 B。
2. && 条件渲染
function Task({ hasError }) {
return (
<div>
<h2>任务详情</h2>
{hasError && <p>任务执行失败</p>}
</div>
);
}
当 hasError 为 true 时才显示错误信息。
注意:如果条件是数字 0,表达式 {count && <Component />} 可能会显示 0。建议写成:
{count > 0 && <TaskList />}
3. 使用 if 提前返回
条件复杂时,可以直接使用 if:
function TaskStatus({ loading }) {
if (loading) {
return <p>加载中...</p>;
}
return <p>加载完成</p>;
}
这种写法通常比多层三元表达式更容易阅读。
六、列表渲染 map()(非常重要)
在 React 中后台开发中,经常需要展示任务列表、用户列表和表格数据。
function TaskList() {
const tasks = [
{ id: 1, name: "任务A" },
{ id: 2, name: "任务B" },
{ id: 3, name: "任务C" }
];
return (
<div>
{tasks.map(task => (
<div key={task.id}>
{task.name}
</div>
))}
</div>
);
}
这里:
map():遍历数组。task:当前数组元素。key={task.id}:帮助 React 识别每个列表元素。
为什么需要 key?
React 更新列表时,需要识别哪些元素被新增、删除或移动。
因此,通常应该使用稳定的业务 ID:
{tasks.map(task => (
<TaskCard key={task.id} task={task} />
))}
不建议在列表可能增删或排序时使用数组下标作为 key。
七、事件绑定(非常重要)
JSX 中可以通过事件属性传入回调函数。
1. onClick
function App() {
const handleClick = () => {
console.log("新增任务");
};
return (
<button onClick={handleClick}>
新增任务
</button>
);
}
重点注意:
// 正确:点击时执行
<button onClick={handleClick}>新增</button>
// 正确:点击时执行并传递参数
<button onClick={() => handleClick(123)}>新增</button>
// 错误:渲染时立即执行
<button onClick={handleClick()}>新增</button>
2. onChange
function App() {
const handleChange = (event) => {
console.log(event.target.value);
};
return (
<input
placeholder="请输入任务名称"
onChange={handleChange}
/>
);
}
在 React 中,最常用的事件包括:
| 事件 | 用途 |
|---|---|
| onClick | 点击按钮 |
| onChange | 输入框内容变化 |
| onSubmit | 表单提交 |
| onFocus | 获得焦点 |
| onBlur | 失去焦点 |
八、Props:组件属性传递(非常重要)
Props 是 React 组件接收外部数据的方式。
可以把 React 组件理解成函数,Props 就是它的输入参数。
例如:
function TaskCard({ name, status }) {
return (
<div>
<h3>{name}</h3>
<p>状态:{status}</p>
</div>
);
}
使用:
function App() {
return (
<div>
<TaskCard
name="回查任务A"
status="运行中"
/>
<TaskCard
name="回查任务B"
status="已完成"
/>
</div>
);
}
这样就实现了组件复用。
动态 Props
const task = {
name: "回查任务",
status: "running"
};
<TaskCard
name={task.name}
status={task.status}
/>
还可以使用展开语法:
<TaskCard {...task} />
相当于把 task 对象中的属性分别传给组件。
九、style 和 className
1. className
<div className="task-card">
任务卡片
</div>
配合 CSS:
.task-card {
padding: 20px;
border: 1px solid #ddd;
}
2. style
HTML:
<div style="color: red; font-size: 20px;">
Hello
</div>
JSX:
<div style={{ color: "red", fontSize: 20 }}>
Hello
</div>
这里的双大括号:
- 外层
{}:嵌入 JavaScript 表达式。 - 内层
{}:JavaScript 对象。
一句话记忆:
{}:告诉 JSX,这里要执行一个 JavaScript 表达式。{{}}:外层{}表示 JavaScript 表达式,内层{}表示 JavaScript 对象。
function App() {
const styles = {
color: "red",
fontSize: 20
};
return (
<div style={styles}>
Hello React
</div>
);
}
注意,React 的样式对象使用驼峰命名,例如 fontSize,而不是 font-size。
十、实战:React 任务管理页面
下面将 JSX 的主要知识点串起来。
import { useState } from "react";
export default function TaskPage() {
const [tasks, setTasks] = useState([
{ id: 1, name: "任务A", status: "running" },
{ id: 2, name: "任务B", status: "done" }
]);
const [taskName, setTaskName] = useState("");
const addTask = () => {
if (!taskName.trim()) return;
const newTask = {
id: crypto.randomUUID(),
name: taskName.trim(),
status: "running"
};
setTasks(prev => [...prev, newTask]);
setTaskName("");
};
const deleteTask = (id) => {
setTasks(prev =>
prev.filter(task => task.id !== id)
);
};
return (
<div className="task-page">
<h2>任务管理系统</h2>
<p>任务总数:{tasks.length}</p>
<input
value={taskName}
placeholder="请输入任务名称"
onChange={(e) => setTaskName(e.target.value)}
/>
<button onClick={addTask}>
新增任务
</button>
{tasks.map(task => (
<div key={task.id}>
<span>{task.name}</span>
<span>
{task.status === "running"
? "运行中"
: "已完成"}
</span>
<button onClick={() => deleteTask(task.id)}>
删除
</button>
</div>
))}
</div>
);
}
核心代码解析
| 代码 | 知识点 |
|---|---|
className="task-page" | JSX 属性 |
{tasks.length} | 动态表达式 |
tasks.map(...) | 列表渲染 |
key={task.id} | 列表标识 |
status === ... ? ... | 条件渲染 |
onClick={addTask} | 事件绑定 |
onChange={...} | 输入事件 |
value={taskName} | 动态属性 |
setTasks(...) | React 状态更新 |
这里 useState 属于 React Hooks,并不是 JSX 语法本身,但实际开发中经常与 JSX 配合使用。
十一、JSX 学习优先级总结
| 知识点 | 优先级 | 掌握要求 |
|---|---|---|
| JSX 标签语法 | P0 | 熟练 |
{} 表达式 | P0 | 熟练 |
| 条件渲染 | P0 | 熟练 |
| map 列表渲染 | P0 | 熟练 |
| onClick / onChange | P0 | 熟练 |
| Props 传值 | P0 | 熟练 |
| className / style | P0 | 熟练 |
| key | P0 | 理解作用 |
| Fragment | P1 | 会使用 |
| JSX 编译原理 | P2 | 了解即可 |
十二、本质
一句话理解:JSX 的本质是 JavaScript 的语法糖,最终会被编译成 JavaScript 函数调用,生成描述 UI 的 React Element(React 元素对象)。
1. 举个最简单的例子
你写的 JSX:
const element = <h1>Hello React</h1>;
经过 Babel 等工具转换后,现代 React 通常相当于:
import { jsx } from "react/jsx-runtime";
const element = jsx("h1", {
children: "Hello React"
});
调用 jsx() 后,会返回一个 JavaScript 对象。
可以简化理解为:
const element = {
type: "h1",
props: {
children: "Hello React"
}
};
注意,这只是简化结构,真实的 React Element 还包含其他字段。
所以 JSX 既不是 HTML,也不是真实 DOM,而是用于描述页面结构的语法。
2.JSX 到页面显示的完整过程
3.为什么需要 JSX?
如果没有 JSX,你可能需要写:
const element = React.createElement(
"div",
null,
React.createElement("h1", null, "任务管理"),
React.createElement("p", null, "任务列表")
);
有了 JSX:
const element = (
<div>
<h1>任务管理</h1>
<p>任务列表</p>
</div>
);
显然 JSX 更直观、更容易维护。
十三、最后总结
JSX 可以理解为 React 用来描述 UI 的语法工具。
实际开发中,最重要的五种写法:
// 1. 动态数据
<h1>{title}</h1>
// 2. 条件渲染
{loading ? <Loading /> : <Content />}
// 3. 列表渲染
{tasks.map(task => (
<div key={task.id}>{task.name}</div>
))}
// 4. 事件绑定
<button onClick={handleClick}>提交</button>
// 5. 组件复用
<TaskCard name="任务A" status="running" />
掌握这五种写法,就能看懂大部分 React 业务组件中的 JSX。
接下来最值得学习的是:
Props → useState → useEffect → 组件通信 → Ant Design 表单与表格实战。