一篇博客带你吃透「为什么看起来像 HTML,其实是 JavaScript」
1. JSX 是什么?
- 官方定义:JavaScript + XML 的语法扩展
- 本质:
React.createElement(component, props, ...children)的语法糖 - 编译时由 Babel/SWC 转译成纯 JS,浏览器不认识 JSX,只认识 React.createElement。
2. Hello JSX:一行代码看透转译
// 你写的 JSX
const element = <h1 className="title">Hello, JSX!</h1>;
// Babel 转译结果
const element = React.createElement(
'h1',
{ className: 'title' },
'Hello, JSX!'
);
3. JSX 与 HTML 的 5 处关键差异
| 场景 | HTML | JSX |
|---|---|---|
| 属性名 | class | className |
| 自闭合 | <img> | <img /> |
| 样式 | style="color:red" | style={{color:'red'}} |
| 表达式 | 不支持 | {1 + 2} |
| 注释 | <!-- --> | {/* 注释 */} |
4. 在标签里嵌入任意 JavaScript
function Avatar({ user }) {
return (
<img
src={user.avatar}
alt={user.name}
style={{
borderRadius: user.isVip ? '50%' : 0,
width: user.isVip ? 80 : 40
}}
/>
);
}
5. 条件渲染与列表渲染
条件
{isLoggedIn ? <LogoutBtn /> : <LoginBtn />}
列表
<ul>
{todos.map(todo =>
<li key={todo.id}>{todo.text}</li>
)}
</ul>
6. Fragment 与空标签:不写多余 DOM
// ❌ 会多一层 <div>
return (
<div>
<Header />
<Main />
</div>
);
// ✅ 不额外生成节点
return (
<>
<Header />
<Main />
</>
);
7. 自闭合组件与 Children
// 无 children
<Icon type="close" />
// 有 children
<Button>
{loading ? 'Loading...' : 'Submit'}
</Button>
8. 常见错误 & 调试技巧
| 报错信息 | 原因 | 解决 |
|---|---|---|
JSX expressions must have one parent | 多个根节点 | 用 <> 或 <div> 包裹 |
Expected corresponding JSX closing tag | 标签未闭合 | 检查 <img> → <img /> |
Cannot use 'class' as a JSX prop | 误用 HTML 属性 | 改为 className |
9. Vite 项目实战:一行命令体验 JSX
npm create vite@latest jsx-demo --template react-ts
cd jsx-demo && npm i && npm run dev
在 App.tsx 里随意改 JSX,保存即热更新,体验 0 延迟。
10. 小结:JSX 记忆口诀
“看上去 HTML,本质是 JS;花括号里写 JS,首字母大写是组件。”