JSX 语法
JSX 是 React 的招牌特性——一种"语法扩展",让你在 JavaScript 里写 HTML 风格的标签。乍看不习惯,但它把"组件长什么样"和"组件有什么逻辑"放在同一个文件里,实际开发效率极高。这一章我们彻底搞懂 JSX 的所有规则。
1. JSX 长什么样
JSX 看起来像 HTML,但它是写在 JavaScript 文件里的:
// JSX:在 JS 里写类似 HTML 的语法
const element = <h1>你好,React!</h1>;
// 这不是字符串,也不是 HTML,是一种"语法扩展"
// 最终会被构建工具编译成下面这种 JS 调用:
// React.createElement("h1", null, "你好,React!")你可能会问:为什么不直接用字符串拼接生成 HTML?因为字符串拼接又慢又难维护(转义、嵌套、XSS 全是坑)。JSX 在构建时会被编译成 React.createElement 调用,最终生成一个普通 JS 对象(虚拟 DOM),React 拿它去高效更新真实 DOM。你写 JSX,React 帮你管 DOM——这就是声明式渲染的本质。
2. 花括号嵌入表达式
JSX 最强大的特性:用花括号把任何 JavaScript 表达式嵌进标签里。这是它和 HTML 模板(如 Vue 的 mustache)最大的不同——花括号里是真正的 JS,不是字符串。
// 花括号里可以嵌入任何 JS 表达式
const name = "小明";
const age = 20;
const greeting = <p>你好,{name},今年 {age} 岁。</p>;
// 表达式可以是任意运算
const total = <p>总价:{10 + 5 * 2} 元</p>;
// 也可以是三元、函数调用
const isAdmin = true;
const tag = <span>{isAdmin ? "管理员" : "访客"}</span>;
// 注意:语句(if、for)不能放在花括号里,只能放表达式关键区别:表达式(有返回值的,如变量、运算、三元、函数调用)能放;语句(if、for、switch)不能放。需要条件判断就用三元,需要循环就用后面讲的 map。
3. 属性写法的特殊之处
JSX 属性和 HTML 类似,但有几个地方必须改:
// 1. class 是 JS 关键字 → 用 className
<div className="card highlight">内容</div>
// 2. style 要写成对象(双花括号:外层 JSX 表达式,内层样式对象)
<div style={{ color: "red", fontSize: "14px" }}>
红色文字
</div>
// 3. 属性名用驼峰:onclick → onClick,maxlength → maxLength
<button onClick={handleClick}>点我</button>
<input maxLength={20} />
// 4. 布尔属性:true 写属性名,false 省略
<input disabled={true} />
<input disabled /> {/* 等价 */}
<input disabled={false} /> {/* 等于不写 */}这些"奇葩"写法的根本原因是:JSX 是 JS 不是 HTML。JS 里 class 是保留字(虽然现在没用了),所以改叫 className;HTML 属性 onclick 全小写,JS 里约定驼峰,所以变成 onClick。记住这两条,后面就不会踩坑。
4. 条件渲染的三种写法
React 里没有 v-if 这种专用指令,条件渲染全部用 JS 本身的语法解决。常用三种:
// 方式 1:三元表达式(二选一)
function Greeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? <h1>欢迎回来!</h1> : <h1>请登录</h1>}
</div>
);
}
// 方式 2:逻辑与 && (条件为真才渲染)
function Mailbox({ unreadMessages }) {
return (
<div>
<h1>邮箱</h1>
{unreadMessages.length > 0 && (
<p>你有 {unreadMessages.length} 条未读消息</p>
)}
</div>
);
}
// 方式 3:提前 return(整个组件提前结束)
function Warning({ isDanger }) {
if (!isDanger) return null; // 不渲染任何东西
return <div className="warning">危险!</div>;
}新手最容易写错的,是在花括号里放 if:
- 错误:
return {if (x) return <a/>}—— 语句不能放花括号。 - 正确:用三元
x ? <a/> : <b/>,或提前 return。
5. 一个组件只能返回一个根元素
JSX 有个硬规则:一个组件的 return 语句只能有一个最外层标签。下面这样会报错:
- 错误:
return (<h1/> <p/>)—— 两个根元素。 - 正确:用一个
<div>包起来,或用 Fragment。
但有时候我们不想多加一个 div(会破坏布局或语义),这时就用 Fragment——它是一个"透明容器",渲染时不产生真实 DOM 节点:
import { Fragment } from "react";
// 方式 1:用 <Fragment> 包裹(可以传 key)
function ItemList({ items }) {
return items.map(item => (
<Fragment key={item.id}>
<dt>{item.term}</dt>
<dd>{item.desc}</dd>
</Fragment>
));
}
// 方式 2:用空标签 <></>(语法糖,但不能传 key)
function TwoLines() {
return (
<>
<h2>标题</h2>
<p>正文段落</p>
</>
);
}日常用空标签 <></> 居多,简短又清晰。需要传 key(比如在 map 里)时才用完整写法 <Fragment>。
6. JSX 也是表达式
这是理解 React 的关键:JSX 不是模板字符串,而是一个真正的 JS 值。它可以赋值、传参、返回:
// JSX 本身也是一个 JS 表达式
const elem = <h1>标题</h1>;
// 可以赋值给变量
const header = <header>{elem}</header>;
// 可以做函数参数
function render(component) {
return <main>{component}</main>;
}
render(<h1>传入的标题</h1>);
// 可以做返回值(这就是组件)
function Title() {
return <h1>函数返回的 JSX</h1>;
}"组件就是返回 JSX 的函数"——这句话的根基就在这里。当你写 function App() { return <h1>...</h1> },本质就是定义了一个返回特定对象的函数。
7. 注释写法
JSX 里的注释有点特殊——既不是 HTML 注释也不是 JS 单行注释,而是花括号包裹的多行注释:
- 标签内:
{/* 这是 JSX 注释 */} - 标签外(组件函数顶部):直接用
//或/* */即可。
小结
JSX 是 React 的"门面":看起来像 HTML,本质是 JS。记住四条铁律——花括号放表达式不放语句、class 改 className、属性名驼峰、单根返回用 Fragment——你就能看懂和写出任何 JSX。下一篇我们看 JSX 的"宿主":函数组件。
← 上一篇 React 环境搭建
下一篇 React 函数组件 →