JSX — 是一种类似XML的JavaScript语法扩展,由React团队开发,用于声明式地描述用户界面。与模板引擎不同,JSX被编译为普通的JavaScript函数调用,在标记内部提供语言的完整能力。根据React, 2024,JSX在所有现代React框架和库中都得到支持。
要点
JSX(JavaScript XML)——JavaScript的一种语法扩展,于2013年首次在React中引入。它允许开发人员以声明式的方式描述用户界面的结构,将标记和逻辑结合在一个文件中。
在JSX出现之前,开发人员使用文本模板(Mustache、Handlebars)或通过document.createElement手动创建DOM元素。两种方法都有缺点:文本模板不进行类型检查,手动创建DOM繁琐且容易出错。
React选择了不同的道路——将标记直接嵌入到代码中。这一决定在社区中引起了争论,但随着时间的推移成为了标准。如今,JSX不仅用于React,还用于SolidJS、Preact、Qwik,甚至通过插件用于Vue。
JSX元素看起来像HTML标签,但直接嵌入在JavaScript中。每个元素被转译为对React.createElement的调用,带有三个参数:元素类型、props对象和子元素。一个根元素——强制规则:JSX表达式必须返回一个父元素或片段。
import React from 'react';
// 基本JSX - 单个根元素
const element = (
<div className="app">
<h1>Hello, World!</h1>
<p>Welcome to React</p>
</div>
);
当不需要额外的DOM节点时,使用React.Fragment或简短语法<></>。片段不创建真实的DOM元素,只对子节点进行分组。这在表格和列表中特别有用,因为额外的包装会破坏HTML结构。
function Columns() {
return (
<>
<td>First</td>
<td>Second</td>
</>
);
}
任何JavaScript表达式都可以通过花括号嵌入到JSX中{ }。内部可以使用变量、函数调用、三元运算符和数组方法。条件渲染通过三元运算符或逻辑AND完成。
function Greeting({ name, isLoggedIn }) {
const items = ['Red', 'Green', 'Blue'];
return (
<div>
{/* Expression with variable */}
<h1>Hello, {name}</h1>
{/* Conditional rendering */}
{isLoggedIn ?
<p>Welcome back!</p :
<button>Login</button>
}
{/* Render array */}
<ul>
{items.map(item =>
<li key={item}>{item}</li>
)}
</ul>
</div>
);
}
关键限制——花括号内只能使用表达式,不能使用语句。不能使用if/else、for、switch——只能使用三元运算符、逻辑运算符和数组方法。允许函数调用,包括箭头函数。
JSX在视觉上类似于HTML,但有着根本的区别。属性以camelCase编写——className代替class,onClick代替onclick,tabIndex代替tabindex。这是因为JSX被转译为JavaScript,而在JavaScript中属性名不允许使用连字符。
| HTML | JSX | 原因 |
|---|---|---|
class="wrapper" | className="wrapper" | class——JS中的保留字 |
onclick="handle()" | onClick={handle} | JS属性的camelCase |
style="color: red" | style={{ color: 'red' }} | 样式对象代替字符串 |
<input disabled> | <input disabled={true}> | 布尔属性的显式指定 |
另一个重要区别——自闭合标签。在HTML中,某些标签(br、hr、input)可以不闭合。在JSX中,所有自闭合标签必须有闭合斜杠:<br />、<input />。SVG属性名也转换为camelCase:strokeWidth、fillOpacity。
浏览器不直接理解JSX。在执行之前,JSX代码通过转译器——Babel、TypeScript或esbuild。每个JSX元素被转换为对createElement或jsx/runtime的调用。
// 原始JSX
const element = <h1 className="title">Hello</h1>;
// 转译后
const element = React.createElement(
'h1',
{ className: 'title' },
'Hello'
);
从React 17开始,出现了一种新的JSX转换,不需要导入React。自动导入jsx-runtime允许在不需要import React from 'react'的情况下编写组件。Babel和TypeScript通过设置{"runtime": "automatic"}来支持这种转换。
虽然JSX与React相关联,但其他框架也使用它。SolidJS使用JSX并编译为真实的DOM节点,无需Virtual DOM。Preact——React的轻量级替代品,完全支持JSX。Vue通过@vue/babel-plugin-jsx支持JSX,尽管其主要模板是template。
关键区别——表达式的语义。在React中,JSX表达式在每次渲染时执行。在SolidJS中,JSX被编译一次,更新通过信号跟踪。这影响性能:SolidJS不需要Virtual DOM和协调,因此JSX渲染更快。
在TypeScript中,JSX在语言级别得到支持。扩展名为.tsx的文件自动处理JSX语法。props的类型化——TypeScript + JSX的主要优势之一:IDE提示预期的属性、回调类型和props的必需性。
编写易于阅读和维护的JSX代码。将复杂表达式提取到单独的变量或函数中——这提高了可读性,并允许独立于标记测试逻辑。使用片段代替不必要的div包装。
缩进规则——为嵌套元素保持缩进。每个嵌套级别——一个缩进级别。闭合标签应与开放标签对齐。对于长属性,使用换行。
避免在props中使用内联箭头函数,如果它们在每次渲染时被创建。在这种情况下,将回调包装在useCallback中或将函数放在组件外部。将复杂组件拆分为更小的组件——每个组件应负责接口的一个逻辑单元。
常见问题
可以,通过Babel插件@babel/plugin-transform-react-jsx可以为任何库配置JSX。SolidJS、Preact、Nerv和其他框架使用JSX配合自己的运行时。为了完全独立,可以将pragma设置为自己的函数。
class是JavaScript中的保留字。JSX被转译为createElement,其中第二个参数是props对象。class属性与ES6类语法冲突,因此React选择了className。
使用模板字符串或classnames库:className={`“btn ${isActive ? 'active' : ''}”`}。对于复杂逻辑,请连接npm包clsx或classnames,它们接受对象和数组。
JSX只支持表达式,不支持语句。对于条件,使用三元运算符、逻辑AND(&&)或逻辑OR(||)。对于复杂逻辑,将条件提取到单独的变量或函数中。
key属性帮助React在重新渲染时识别列表元素。没有key时,React在更改时重绘整个列表。使用唯一key时,React重用DOM节点并重新排序元素,而不是重新创建它们。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。