深入理解 React 中的 JSX:语法本质、三大规则与 HTML 转换实战指南
【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum
导读
本文围绕 React 学习路径中 what_is_jsx.md 一课展开,系统讲解 JSX 是什么、为什么 React 需要它、使用 JSX 必须遵守的三大规则,并手把手演示如何把一段合法 HTML 逐步改写成可用的 JSX 代码。读完本文,你将能够理解 JSX 与 HTML 的本质差异,掌握className、strokeWidth等 camelCase 属性写法,并能在自己的 React 组件中写出无报错的 JSX。
什么是 JSX?
JSX 是 JavaScript 的一种语法扩展(syntax extension),它允许你在 JavaScript 文件中书写类似 HTML 的标记。在编写 React 组件时,JSX 并不是必需的,但它能让组件的书写更加简洁直观。
本质上,JSX 是 ReactcreateElement函数的语法糖(syntactic sugar)。createElement会创建一个 React 元素——一个普通 JavaScript 对象,因此 JSX 最终会被编译成普通的 JavaScript 对象,而非直接的 DOM 节点。
在浏览器控制台中对一个包含文本的divJSX 元素执行console.log,可以看到如下输出:
从输出可以看到,一个 JSX 元素在运行时就是一个结构化对象,核心字段包括:
$$typeof: Symbol(react.element):React 元素的类型标识,用于与普通 JavaScript 对象区分;type: 'div':元素类型,此处为 HTML 标签名字符串;props: { children: 'Example text' }:元素的属性集合,JSX 中包裹的文本会进入children;key: null、ref: null:分别为列表渲染标识和 DOM 引用,未设置时默认为null。
这说明 JSX 不是模板字符串,也不是 HTML,而是一种声明式的、描述 UI 的数据结构。
为什么使用 JSX?
在大多数应用中,渲染逻辑与标记(markup)天生是耦合的——一个按钮的样式、文案和点击行为总是同时被设计和维护。传统做法往往把逻辑与标记拆到不同文件,而 JSX 允许 React 通过组件把渲染逻辑与内容放在同一处,实现真正的"关注点分离"。
此外,JSX 还带来两个直观收益:
- 更直观、更具可视化:在代码中就能"看到"UI 结构,编写体验接近 HTML;
- 更友好的错误提示:React 能够基于 JSX 结构给出更有用的错误与警告信息。
三条核心规则:为什么不能直接复制 HTML 到组件中?
如果你把一段合法的 HTML 原样复制进 React 组件,它大概率无法正常工作。原因在于 JSX 实现了一些 HTML 中没有的规则。下面是必须遵守的三条规则,每条都配有正确与错误的对照示例。
规则一:返回单个根元素
一个组件只能返回一个根元素。如果希望返回多个元素,必须用父标签包裹它们——可以是<div>,如果不想引入多余容器,则可以使用 React Fragment,写法为<>Children</>。
正确写法:
function App() { // 也可以把 <></> 替换成 <div></div> return ( <> <h1>Example h1</h1> <h2>Example h2</h2> </> ); }错误写法:
function App() { return ( <h1>Example h1</h1> <h2>Example h2</h2> ); }规则二:闭合所有标签
在 HTML 中,许多标签是自闭合或可省略闭合的;但在 JSX 中,所有标签都必须显式闭合。例如<input>要写成<input />,<li>要写成<li></li>。
正确写法:
function App() { return ( <> <input /> <li></li> </> ); }错误写法:
function App() { return ( <> <input> <li> </> ); }规则三:大部分属性使用 camelCase 命名
JSX 最终会被编译成 JavaScript,元素属性会变成 JavaScript 对象的键,因此不能使用连字符(dash),也不能使用class这类保留字。很多 HTML 属性因此改为驼峰命名:stroke-width写成strokeWidth,class写成className。
正确写法:
function App() { return ( <div className="container"> <svg> <circle cx="25" cy="75" r="20" stroke="green" strokeWidth="2" /> </svg> </div> ); }错误写法:
function App() { return ( <div class="container"> <svg> <circle cx="25" cy="75" r="20" stroke="green" stroke-width="2" /> </svg> </div> ); }实战演练:把 HTML 转换为 JSX
掌握了三条规则后,我们通过一个完整例子体验"HTML → JSX"的转换过程。假设你有如下一段 HTML,希望从 React 组件中返回它:
<h1>Test title</h1> <svg> <circle cx="25" cy="75" r="20" stroke="green" stroke-width="2" /> </svg> <form> <input type="text"> </form>如果你直接把这段代码放进 React 组件,会得到许多报错。建议在自己的本地环境中跟随操作,也可以使用 react.new 在浏览器中快速获得一个可用的 React 环境。
第一步:补上单一根元素
第一个报错是"没有返回单个根元素",因此先给它套一个容器:
<div> <h1>Test title</h1> <svg> <circle cx="25" cy="75" r="20" stroke="green" stroke-width="2" /> </svg> <form> <input type="text"> </form> </div>此时屏幕上会冒出另一个报错——这不是你的修改引入了新问题,而是 React 之前还没有暴露这个错误。
第二步:闭合<input>标签
第二个问题是<input>标签没有闭合:
<div> <h1>Test title</h1> <svg> <circle cx="25" cy="75" r="20" stroke="green" stroke-width="2" /> </svg> <form> <input type="text" /> </form> </div>跟随操作的话,此刻屏幕上的报错会消失,但控制台(console)中仍会出现警告。
第三步:将属性改为 camelCase
最后一个问题是属性没有驼峰化,使用了 JSX 中非法的 DOM 属性,具体是stroke-width:
<div> <h1>Test title</h1> <svg> <circle cx="25" cy="75" r="20" stroke="green" strokeWidth="2" /> </svg> <form> <input type="text" /> </form> </div>完成这三处修正后,React 给出的所有报错都被解决,这就是一段可以在 React 组件中直接使用、无任何问题的完整 JSX 代码。
延伸:JSX 在课程中的承接关系
在《The Odin Project》的 React 学习路径中,本课处于"从零上手 React"(getting_started_with_react)阶段,它与相邻几课共同构成 JSX 的知识闭环:
- react_components.md 中明确指出组件函数返回的就是 JSX,且React 组件名必须大写——当 JSX 被解析时,React 正是靠大小写区分 HTML 标签与组件实例:
<greeting />会被当成普通 HTML 元素,而<Greeting />才是组件。这也是为什么组件文件中的import、函数名与使用处都要保持大写; - passing_data_between_components.md 中所有示例都用 JSX 书写 props,例如
<Button text="Click Me!" color="blue" fontSize={12} />,其中花括号{}用于在 JSX 中嵌入 JavaScript 表达式; - rendering_techniques.md 展示了如何用
{animals.map(...)}在 JSX 中渲染列表,以及用三元运算符、&&操作符进行条件渲染——这些都是"在 JSX 中写 JavaScript"的直接体现; - keys_in_react.md 则解释了列表渲染中
<li key={animal}>的key属性为何必要:动态列表的项数、顺序可能变化,React 需要稳定的key来跨渲染识别组件实例。
动手实践时,你可以参照 setting_up_a_react_environment.md 用 Vite 创建项目,然后新建Greeting.jsx之类的文件,把本文的示例代码替换进main.jsx中createRoot(...).render(...)的 JSX 区域,即可立刻看到 JSX 的效果与报错行为。
小结与自查
本文从 JSX 的本质(createElement的语法糖、编译为普通对象)讲起,说明了 React 选择 JSX 的理由,并重点拆解了三条核心规则(单一根元素、闭合所有标签、属性 camelCase),最后通过一段 HTML 的逐步转换演示了错误排查全过程。
可以用下面几个问题检验自己是否掌握:
- 什么是 JSX?它是 JavaScript 的语法扩展,是
createElement的语法糖,编译后是普通 JavaScript 对象。 - 为什么使用 JSX?让渲染逻辑与内容在同一组件中耦合、更直观可视化、错误提示更友好。
- JSX 的三大规则是什么?返回单一根元素、闭合所有标签、大部分属性使用 camelCase。
- 如何在 JSX 中引用动态值?使用花括号
{}包裹 JavaScript 表达式,这一能力在后续列表渲染与条件渲染课程中会频繁使用。
【免费下载链接】curriculumThe open curriculum for learning web development项目地址: https://gitcode.com/GitHub_Trending/cu/curriculum
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考