一、JSX 是什么?React 开发者的 “可视化 UI 编辑器”
(一)一句话理解 JSX
JSX(JavaScript XML)是 React 独创的语法糖,允许在 JavaScript 中直接书写类似 HTML 的标签结构,让 UI 开发像拼积木一样直观。比如:
function Welcome() {
return <h1>Hello, React世界!</h1>; // 这不是HTML,是能运行的JSX
}
(二)为什么 React 选择 JSX?三大核心优势
- 读写友好:比纯 JS 的
createElement链式调用更直观,一眼看清 UI 结构(想象一下用纯 JS 写嵌套 10 层的 DOM 有多酸爽) - 逻辑融合:在标签中直接嵌入 JS 表达式,数据驱动视图更丝滑(
{user.name}随手用,再也不用拼接字符串) - 类型安全:编译阶段就能捕获标签拼写、属性错误,减少运行时 BUG(妈妈再也不用担心我写错 class 啦~)
二、JSX 核心特性解析:从语法糖到运行时
(一)这些语法规则必须牢记!
- 标签闭合规则:所有标签必须正确闭合,单标签用
/>结尾(别漏啦) - 唯一根节点:组件返回值必须有单个顶层容器(加个
<div>或者<>碎片标签) - 属性命名规范:采用小驼峰命名(
className代替class,htmlFor代替for)
(二)JSX 中的 JS 表达式怎么用?
function App() {
const isLogin = true;
const user = { name: "稀土掘金用户" };
const todoList = ["学JSX", "写组件", "搞实战"];
return (
<div>
<h2>今天的目标:{todoList[0]}</h2> {/* 变量引用 */}
{isLogin ? <Button>退出登录</Button> : <LoginForm />} {/* 条件渲染 */}
<ul>
{todoList.map((item, index) => ( // 列表渲染,记得加key!
<li key={index}>{item}</li>
))}
</ul>
</div>
);
}
(三)JSX 能直接运行吗?浏览器:这题我不会!
-
答案:不能!需要 Babel 编译器翻译成
React.createElement函数调用 -
转换过程:
// 源码 <h1 className="title">Hello, world</h1> // 编译后(React 17+) import { jsx as _jsx } from "react/jsx-runtime"; _jsx("h1", { className: "title", children: "Hello, world" }); -
小知识:React 17 之前必须手动引入
React,现在编译器会自动处理啦~
三、JSX vs React.createElement:效率与性能的双重升级
(一)两种写法的本质区别
| 特性 | JSX 写法 | createElement 写法 |
|---|---|---|
| 可读性 | 直观的 HTML 结构,层级一目了然 | 嵌套的函数调用,容易看花眼 |
| 开发效率 | 快速编写 UI,减少模板字符串拼接 | 手动处理属性和子节点,容易出错 |
| 编译优化 | Babel 自动处理引号、转义等细节 | 需手动处理属性类型和子节点格式 |
(二)实战代码对比:列表渲染的两种实现
// JSX写法(简洁派)
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
// createElement写法(底层派)
function TodoList({ todos }) {
return React.createElement("ul", null,
todos.map(todo =>
React.createElement("li", { key: todo.id }, todo.title)
)
);
}
四、避坑指南:JSX 开发常见问题及解决方案
(一)表达式 vs 语句:这些坑别踩!
-
错误示范:JSX 中不能直接写
if语句{if (isShow) <div>显示内容</div>} // 报错! -
正确姿势:用三元表达式或逻辑与运算符
{isShow ? <div>显示内容</div> : null} // 或者 {isShow && <div>显示内容</div>}
(二)样式怎么写?两种方案任你选
-
内联样式:使用驼峰命名的 JS 对象
<div style={{ fontSize: "20px", color: "red" }}>红色大字体</div> -
外部样式:通过
className引用 CSS 类(推荐复杂样式)<div className="container">外部样式更清晰</div>
(三)key 值的正确用法:性能优化关键
- 作用:帮助 React 识别列表项变化,避免不必要的重新渲染
- 最佳实践:优先使用数据中的唯一标识(如 id),避免用 index(数据顺序变化时会出 bug!)
五、从入门到实战:完整组件开发示例
(一)组件代码:带交互的 TODO 列表
import { useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([
{ id: 1, title: "学习JSX核心语法" },
{ id: 2, title: "完成稀土掘金实战文章" }
]);
const addTodo = (title) => {
setTodos([...todos, { id: Date.now(), title }]);
};
return (
<div className="todo-app">
<h1>我的TODO列表</h1>
<TodoInput onAdd={addTodo} />
<TodoList todos={todos} />
</div>
);
}
// 子组件:输入框
function TodoInput({ onAdd }) {
const [input, setInput] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
if (input.trim()) {
onAdd(input);
setInput("");
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="添加新任务"
/>
<button>添加</button>
</form>
);
}
// 子组件:列表渲染
function TodoList({ todos }) {
return (
<ul className="todo-list">
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}
</ul>
);
}
// 子组件:单个任务项
function TodoItem({ todo }) {
return (
<li className="todo-item">
{todo.title}
</li>
);
}
(二)代码亮点解析
- 组件化拆分:将功能拆分为父组件、输入框、列表、单个任务项,结构清晰易维护
- 状态管理:使用
useState管理 TODO 数据,父子组件通过 props 通信 - JSX 应用:列表渲染、条件判断、样式绑定等常用场景一网打尽
六、总结:JSX 为什么是 React 开发的核心竞争力?
-
声明式编程:用标签直接描述 UI,告别繁琐的 DOM 操作(写 UI 就像画画一样直观)
-
学习曲线平滑:会 HTML 和 JS 就能快速上手,降低 React 入门门槛
-
生态兼容性:Babel、TypeScript 等工具全面支持,适配现代前端开发流程
掌握 JSX 就像拿到了 React 开发的钥匙,无论是简单组件还是复杂应用,它都能让你的代码兼具可读性和高效性。现在就打开编辑器,用 JSX 写出你的第一个 React 组件吧~记得给列表项加上唯一 key 哦,这可是 React.diff 算法的小秘密~