在 React 世界里,JSX 就是我们的母语。它不是字符串,也不是 HTML,而是一套能够在 JavaScript 中直接书写 UI 结构的语法糖。很多初学者一看到“在 JS 里写 HTML”就本能排斥,但真正用熟之后,你会发现:这才是现代前端最自然、最高效的开发方式。
今天用 5 个逐步递进的真实业务场景 + 完整可运行代码,带你从“看不懂 JSX”到“爱上 JSX”。
一、JSX 本质:只是 createElement 的语法糖
jsx
const element = <h2>JSX 是 React 中用于描述用户界面的语法扩展</h2>;
// 等价于
const element2 = createElement(
'h2',
null,
'JSX 是 React 中用于描述用户界面的语法扩展'
);
所有 JSX 最终都会被 Babel 编译成 React.createElement 调用。记住这一点,你就永远不会被它的“怪模样”吓到。
二、为什么 React 敢把“模板”彻底干掉?
Vue 仍然保留 template,React 却把 UI 完全交给 JS,原因只有一句话:
当 UI 足够复杂时,逻辑必然会入侵模板,而模板语言表达复杂逻辑的能力极弱。
jsx
// Vue template 要写成这样(v-for + v-if + 三元表达式嵌套)
<div v-if="todos.length">
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.done ? '[已完成]' : '[未完成]' }} {{ todo.title }}
</li>
</ul>
</div>
// React JSX:直接用 JS 该怎么写就怎么写
{todos.length > 0 ? (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.done ? '[已完成]' : '[未完成]'} {todo.title}
</li>
))}
</ul>
) : (
<div className="empty">暂无代办事项</div>
)}
你感受一下哪个更清晰、更自由?
三、状态驱动 UI:useState + JSX 的黄金组合
jsx
function App() {
const [name, setName] = useState("Vue");
const [todos] = useState([
{ id: 1, title: "学习 React", done: false },
{ id: 2, title: "学习 Vue", done: true }
]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
// 2 秒后自动切换,展示响应式更新
setTimeout(() => setName("React"), 2000);
return (
<>
<h1>
Hello <span className="title">{name}</span>
</h1>
{todos.length > 0 ? (
<ul className="todo-list">
{todos.map(todo => (
<li key={todo.id} className={todo.done ? 'done' : ''}>
{todo.title}
</li>
))}
</ul>
) : (
<div>暂无代办事项</div>
)}
<div className="login-status">
{isLoggedIn ? "已登录" : "未登录"}
</div>
<button onClick={() => setIsLoggedIn(!isLoggedIn)}>
{isLoggedIn ? "退出登录" : "登录"}
</button>
</>
);
}
这就是 React 的核心哲学:数据变 → 组件函数重新执行 → 生成新的 UI 描述 → React 智能 Diff → 最小化更新 DOM。
四、组件才是王道:用 JSX 像搭积木一样构建页面
传统前端以“页面”为单位,React 以“组件”为单位。来看一个完整的掘金首页布局:
jsx
// 头部组件
function JuejinHeader() {
return (
<header className="juejin-header">
<h1>稀土掘金</h1>
<nav>
<a href="/">首页</a>
<a href="/tags">标签</a>
<a href="/search">搜索</a>
</nav>
</header>
);
}
// 文章列表组件
const Articles = () => {
return (
<main className="articles">
<article>2025 年前端趋势分析</article>
<article>你还在手写 useEffect 依赖数组?</article>
{/* 省略 20 篇 */}
</main>
);
};
// 侧边栏签到组件
const Checkin = () => {
return (
<div className="checkin-widget">
<h3>每日签到</h3>
<button>立即签到 +5 矿石</button>
</div>
);
};
// 热门文章组件
const HotArticles = () => {
return (
<div className="hot-articles">
<h3>24 小时热门</h3>
<ol>
<li>React 19 发布了!</li>
<li>TypeScript 5.6 性能提升 60%</li>
</ol>
</div>
);
};
// 根组件:组合一切
function App() {
return (
<div className="juejin-homepage">
<JuejinHeader />
<div className="container">
<section className="main-content">
<Articles />
</section>
<aside className="sidebar">
<Checkin />
<HotArticles />
</aside>
</div>
</div>
);
}
export default App;
这就是组件化开发的魅力:每个组件职责单一、独立可复用、组合方式无限。
五、为什么说“函数就是组件”?
在 React 里,只要一个函数返回了 JSX,它就是一个组件。原因非常纯粹:
- JS 本身就是函数式语言
- 函数天然具备闭包、参数、返回值
- 配合 Hooks,函数组件的能力已经全面超越 class 组件
jsx
// 2025 年,你应该这样写组件
const Button = ({ onClick, children, variant = "primary" }) => {
return (
<button className={`btn btn-${variant}`} onClick={onClick}>
{children}
</button>
);
};
// 使用
<Button onClick={handleLogin} variant="danger">
退出登录
</Button>
六、JSX 不是“怪语法”,而是未来
很多人初学 React 时最大的心理障碍就是 JSX,但真正用 3 个月后,99% 的人再也不想回到模板语法。
因为:
- 逻辑和视图终于在同一个地方,不用再来回切换文件
- 所有 JS 能力(三元、map、filter、async/await)都可以直接用在 UI 中
- 组件就是函数,组合性、复用性、测试性都达到了极致
当你写出第一个 200 行的 JSX 组件,发现它居然如此清晰易读时,你就会明白 Facebook 当年为什么敢 All in JSX。