以下是完整的语法规则体系:
一、基本语法规则
1. 必须有一个根元素
JSX 表达式必须被单一父元素包裹,否则会语法错误。
jsx
// ❌ 错误:多个根元素
const App = () => {
return (
<h1>标题</h1>
<p>段落</p>
);
};
// ✅ 正确:使用 div 包裹
const App = () => {
return (
<div>
<h1>标题</h1>
<p>段落</p>
</div>
);
};
// ✅ 正确:使用 Fragment 避免额外 DOM 节点
const App = () => {
return (
<>
<h1>标题</h1>
<p>段落</p>
</>
);
};2. 标签必须闭合
所有标签都必须有闭合标记,包括自闭合。
jsx
// ❌ 错误:未闭合
const App = () => {
return <img src="logo.png">;
};
// ✅ 正确:自闭合标签用 />
const App = () => {
return <img src="logo.png" />;
};
// ✅ 正确:普通标签必须有结束标签
const App = () => {
return <div>内容</div>;
};常见自闭合标签:<img />, <input />, <br />, <hr />
二、JavaScript 表达式嵌入
1. 使用 {} 包裹表达式
在 JSX 中,任何 JavaScript 表达式都需用 {} 包裹。
jsx
const name = "React";
const age = 18;
const isActive = true;
const App = () => {
return (
<div>
{/* 变量 */}
<h1>{name}</h1>
{/* 运算 */}
<p>明年年龄:{age + 1}</p>
{/* 函数调用 */}
<p>{name.toUpperCase()}</p>
{/* 条件渲染(三元表达式) */}
<p>{isActive ? "活跃" : "离线"}</p>
{/* 逻辑与(短路渲染) */}
{isActive && <span>✓</span>}
</div>
);
};2. 语句不支持
{} 中不能放置语句(如 if、for),只能放表达式。
jsx
// ❌ 错误:if 语句
const App = () => {
return (
<div>
{if (isActive) { return <span>在线</span> }}
</div>
);
};
// ✅ 正确:三元表达式
const App = () => {
return (
<div>
{isActive ? <span>在线</span> : <span>离线</span>}
</div>
);
};
// ✅ 正确:提前计算
const App = () => {
let status;
if (isActive) {
status = <span>在线</span>;
} else {
status = <span>离线</span>;
}
return <div>{status}</div>;
};三、属性(Props)规则
1. camelCase 命名
HTML 属性名需转换为驼峰命名法。
jsx
// ❌ 错误:HTML 属性名
const App = () => {
return <div class="box" tabindex="0">内容</div>;
};
// ✅ 正确:React 属性名
const App = () => {
return <div className="box" tabIndex="0">内容</div>;
};
// 常见转换表:
// class → className
// for → htmlFor
// tabindex → tabIndex
// onclick → onClick
// onchange → onChange2. 动态属性
属性值可以是 JavaScript 表达式。
jsx
const url = "https://example.com";
const isDisabled = false;
const App = () => {
return (
<a href={url} target="_blank">
链接
</a>
);
};
// 布尔属性:值为 true 时省略,false 时省略属性
const App = () => {
return <button disabled={isDisabled}>点击</button>;
// 当 isDisabled=false 时,等价于 <button>点击</button>
};3. 特殊属性值
- 字符串:可用双引号或单引号
- 数字:必须用
{}包裹 - 样式对象:
style接受对象,属性名用驼峰
jsx
const App = () => {
return (
<div
className="container" // 字符串
data-id="123" // 自定义属性可用连字符
style={{ // 样式对象
backgroundColor: 'lightblue',
fontSize: 16
}}
>
内容
</div>
);
};四、子元素规则
1. 文本节点
文本可直接写在标签内,特殊字符自动转义。
jsx
const App = () => {
return (
<div>
{/* 普通文本 */}
普通文本
{/* 自动转义:防止 XSS */}
{"<script>alert('xss')</script>"} {/* 显示为纯文本 */}
</div>
);
};2. 列表渲染
数组自动展开,需为每个元素提供唯一 key。
jsx
const items = ['Apple', 'Banana', 'Orange'];
const App = () => {
return (
<ul>
{items.map((item, index) => (
// ✅ 正确:使用唯一 key
<li key={index}>{item}</li>
))}
</ul>
);
};3. Fragment 分组
避免额外 DOM 节点。
jsx
const App = () => {
return (
<>
<td>单元格1</td>
<td>单元格2</td>
</>
);
};五、注释方式
JSX 中注释需用大括号包裹 {/* ... */}。
markdown
const App = () => {
return (
<div>
{/* 这是单行注释 */}
<h1>标题</h1>
{/*
多行注释
可以写多行
*/}
</div>
);
};六、常见陷阱与限制
1. className 不是 class
jsx
// ❌ 错误
<div class="box">内容</div>
// ✅ 正确
<div className="box">内容</div>2. style 不是字符串
jsx
// ❌ 错误
<div style="color: red;">内容</div>
// ✅ 正确
<div style={{ color: 'red' }}>内容</div>3. 事件处理函数不是字符串
jsx
// ❌ 错误
<button onclick="handleClick()">点击</button>
// ✅ 正确
<button onClick={handleClick}>点击</button>4. **自闭合标签必须带 / **
jsx
// ❌ 错误
<br>
// ✅ 正确
<br />5. ** 组件必须大写 **
jsx
// ❌ 错误:小写被视为 HTML 标签
const mycomponent = () => <div>内容</div>;
// ✅ 正确:大写开头
const MyComponent = () => <div>内容</div>;七、** JSX 与 HTML 关键区别总结 **
markdown
| 特性 | HTML | JSX |
| -------- | --------------------- | ------------------------------- |
| 属性命名 | `class`, `tabindex` | `className`, `tabIndex` |
| 自闭合 | `<br>` | `<br />` |
| 事件 | `onclick` | `onClick` |
| 内联样式 | `style="color:red"` | `style={{ color: 'red' }}` |
| 注释 | `<!-- -->` | `{/* */}` |
| 表达式 | 不支持 | 支持 `{expression}` |
| 布尔属性 | `disabled="disabled"` | `disabled={true}` 或 `disabled` |核心要点
- 本质是语法糖:JSX 编译为
React.createElement调用 - JavaScript 优先:在
{}中写 JavaScript 表达式 - HTML 兼容但有差异:属性用驼峰,事件处理用函数
- 必须单一根元素:使用 Fragment 避免多余 DOM
- key 很重要:列表渲染时提供唯一 key 提升性能
掌握这些规则,就能在 React 中自如地使用 JSX 构建 UI。
