HTML → JSX / React 转换器,免费

自动将 HTML 转换为兼容 React 的 JSX。处理 class→className、for→htmlFor、style 对象、事件处理、自闭合标签等。

输入与输出

选项

工作原理

  1. 粘贴 HTML:在输入区输入标准 HTML 片段 · div、表单、表格或完整代码块。
  2. 选择选项:按需启用 React Fragment 包裹和美化输出。
  3. 立即获得 JSX:转换器会自动将 class 转为 classNamefor 转为 htmlFor,将 style 字符串转为 style 对象,并闭合自闭合标签。
  4. 复制到项目中:将 JSX 输出直接粘贴到您的 React 组件中。

为什么使用 HTML → JSX?

将 HTML 模板迁移到 React 时,手动转换容易出错。忘记一个 className 或留下未闭合的标签都会导致构建失败。此转换器自动处理所有必要变更 · 包括将 style 属性中 background-color 等 CSS 属性名转为驼峰的 backgroundColor、将事件处理器字符串转为函数引用,以及正确闭合 void 元素。这能加速原型设计、代码迁移,并帮助不熟悉 JSX 语法差异的开发者。

关键转换

  • class → className · React 组件中必需
  • for → htmlFor · 用于 label 元素
  • style 字符串 → 对象 · 例如 "color:red"{color:'red'}
  • 自闭合标签 · <br><br />
  • Fragment 包裹 · 可选的外部 <>…</>

JSX究竟是什么

JSX代表「JavaScript XML」。它是由Facebook的Jordan Walke于2013年发明的JavaScript语法扩展,作为JSConf US上React原始发布的一部分。JSX允许您在JavaScript代码中直接编写类XML标记:<div className="hello">World</div>,然后转译器(现在几乎总是Babel)将其编译为普通函数调用:React.createElement('div', {className: 'hello'}, 'World')。浏览器从不直接看到JSX;最终交付的是普通JavaScript。

Walke最初的动机是模板语言(Mustache、Handlebars、Angular的旧指令)是宿主语言的二等公民,它们无法原生使用JavaScript的循环、条件判断或变量,所以每种都重新发明了自己的一套。JSX颠倒了这种关系:它不是偶尔执行JavaScript的模板,而是给了您偶尔执行标记的JavaScript。{condition && <Item />}是一个普通的JS表达式、返回一个React元素,这才是核心思想所在。

自React 17(2020年10月)起,自动JSX运行时意味着您不再需要在每个使用JSX的文件中import React from 'react',Babel会自动插入运行时导入。JSX也已在React本身之外被广泛采用:PreactSolidQwikHono JSXMillionLit以及TypeScript的.tsx都使用相同的语法。facebook.github.io/jsx上的JSX草案规范有意保持框架无关性。

HTML→JSX的全部差异

  • 保留字重命名。classclassName(因为class是JS中的保留字)。forhtmlFor(同理,for是循环关键字)。这是最先让所有人踩坑的两个。
  • 所有其他属性使用驼峰命名。tabindextabIndexreadonlyreadOnlymaxlengthmaxLengthcontenteditablecontentEditable
  • 两个重要例外保留短横线命名。aria-*属性(aria-labelaria-hidden)和data-*属性(data-testid)保留HTML形式。xmlns同理。
  • 空元素必须自闭合:<br>变为<br /><img>变为<img /><input>变为<input />。JSX是XML严格的,而HTML是宽容的。
  • 内联样式接受对象而非字符串。style="color: red; background-color: blue"变为style={{ color: 'red', backgroundColor: 'blue' }}。注意三件事:双花括号(外层是JSX表达式,内层是对象字面量)、驼峰属性名、字符串值加引号。数字像素值省略单位:marginTop: 16,而非'16px'
  • 事件处理器使用驼峰命名并接受函数引用。onclick="handleClick()"变为onClick={handleClick}:注意括号已消失。onClick={handleClick()}会在渲染时调用handleClick并将返回值赋为处理器,这几乎总是一个bug。
  • 注释在JSX内使用{/* … */},而非<!-- … -->。HTML注释语法在JSX内没有意义。
  • Fragment包裹多个同级元素。组件必须返回单个根元素,因此多个顶层元素需要用<>…</>(或较长的<React.Fragment>…</React.Fragment>)包裹。
  • 条件渲染使用JS表达式。{isVisible && <Item />}仅在条件为真值时渲染该元素;{condition ? <A /> : <B />}从两者中选其一。
  • 文本中的花括号需要转义。JSX文本内容中的字面{被解释为表达式的开始。使用{'{'}或等效的HTML实体。

SVG、无障碍访问及其他

SVG在JSX内遵循相同的驼峰命名规则处理大多数属性:viewBoxstrokeWidthfillOpacity。值得注意的例外:xlink:href使用特殊的xlinkHref拼写(现已弃用,转而使用普通的href),xmlns保持原样。无障碍属性遵循ARIA本身的短横线命名约定:aria-labelaria-describedbyrole均按原样保留。

对于CSS,JSX的内联style对象是一个选项。大多数生产代码库使用三种更丰富的替代方案之一:CSS Modules(由打包器编译的每文件作用域类名)、Tailwind CSS(通过className干净传递的实用类)或CSS-in-JS库如styled-components、Emotion或Vanilla Extract。自2022年起,Tailwind已成为新项目中最常见的选择;将HTML移至JSX时,Tailwind类根本不需要转换,它们作为普通className字符串直接传递。

常见转换陷阱

  • 调用函数的内联事件处理器。HTML中的onclick="alert(1)"通常变为JSX中的onClick={() => alert(1)},用箭头函数包裹,使alert在点击时触发而非在渲染时。直接产出onClick={alert(1)}的简单转换器会在渲染时弹出alert,而非用户点击时。本转换器处理常见情况,但值得检查一下输出。
  • HTML注释会被删除。大多数JSX转换器会去掉HTML注释而非将其转换为{/* */}形式,因为后者只在JSX内的特定位置有效。在需要的地方手动添加注释。
  • SVG属性重命名并不总是由自动转换器处理。stroke-widthfill-ruleclip-pathtext-anchor都需要驼峰形式,如果您从Heroicons或Lucide等图标集粘贴SVG,请仔细检查输出。
  • 布尔属性。HTML中的<input disabled>变为JSX中的<input disabled />。HTML中的<input disabled="false">实际上是禁用状态(任何值都会启用它),但在JSX中disabled={false}正确地表示关闭,JSX语义比HTML的更合理。
  • HTML实体。&copy;在JSX文本内容中有效,但使用字面Unicode字符(©)更受推荐。&nbsp;同理。
  • tabindex的情形。应为tabIndex。容易忘记,因为值通常是0-1,看起来像数字,但属性名仍然需要驼峰命名。

适合使用此工具的场景

  • 将服务器渲染模板迁移到React。粘贴现有站点HTML的一块并获取JSX是典型用例。
  • 引入图标、徽章或设计工具导出内容。Heroicons、Lucide、Figma的「以SVG复制」都给您提供需要重命名处理的原始HTML/SVG。
  • 将Tailwind UI / Flowbite / DaisyUI代码片段从HTML示例转换为React项目的JSX。Tailwind类保持不变;只有结构属性需要转换。
  • 为熟悉HTML但不熟悉JSX的开发者入门:自动应用机械规则比阅读差异列表更快。
  • 快速原型设计:当您为草图目的用纯HTML起草了标记,希望将其放入React组件时。

输出适用于任何JSX消费方:React、Preact、Solid、Qwik、Hono JSX、Million、Lit的html模板字面量(需做少量调整)。它适用于React Native,后者使用<View><Text>等原生基础组件,而非HTML元素。

更多问题

JSX和HTML有什么区别?

HTML是浏览器直接解析的标记语言。JSX是编译为React.createElement调用的JavaScript表达式语法,它从不以JSX形式到达浏览器。JSX看起来是XML严格的(每个标签必须关闭,属性使用驼峰命名),因为它作为JavaScript表达式被解析,而非作为宽容的HTML。视觉上的相似是刻意为之,但底层语义相当不同。

在每个JSX文件中还需要导入React吗?

自React 17(2020年10月)起就不需要了,该版本引入了自动JSX运行时。有了它,Babel会自动为您注入必要的运行时导入,因此只使用JSX的文件不需要文件顶部的import React from 'react'。经典运行时对旧工具链仍然可用。大多数新项目使用自动运行时。

可以在不使用React的情况下使用JSX吗?

可以。JSX是一种通用语法,在facebook.github.io/jsx有草案规范,许多框架都使用它:Preact、Solid、Qwik、Hono JSX、Million、Lit,以及htm标记模板变体。这些框架在JSX编译为什么上有所不同(Preact使用h(…),Solid编译为细粒度响应式原语等),但语法是共享的。

为何样式接受对象而非字符串?

因为JSX表达式语法已经提供了花括号来嵌入JavaScript值,而对象字面量是属性集合最自然的JS表示方式。样式对象还允许数字(大多数自动添加px单位)和JS表达式,而字符串无法做到。代价是略显笨拙的双花括号style={{ … }}语法:外层花括号表示「这是一个JSX表达式」,内层花括号表示对象字面量。

有任何内容会发送到服务器吗?

不会。转换逻辑是纯JavaScript,遍历您的HTML字符串并重写属性,全部在您的浏览器中进行。您粘贴的HTML从不离开页面,在迁移包含API端点的私有内部模板或组件标记时非常有用。