1. JSX是什么?
js
<h1 hello="world">Hello, world!</h1>
JSX是一种JavaScript的语法扩展,它看起来非常像HTML。在React中,它被用来描述UI应该是什么样子。通过在JavaScript代码中嵌入HTML标签(实际上是JSX标签),我们可以更直观地描述组件的结构和内容。这使得在JavaScript中创建和操作UI元素变得更加容易。
2. JSX是谁提出来的?
JSX最早由Facebook提出并推广,作为React框架的一部分。然而,JSX并不强制要求只能用于React,它也可以在React之外的框架中使用,例如Vue.js和Solid等。
3. 为什么使用JSX?
- 可读性:JSX提供了类似于HTML的语法,这使得开发人员可以更容易地理解和编写UI代码。
- 类型安全:在JSX中,属性和子元素都经过了类型检查,这有助于在开发过程中捕获错误。
- 抽象层:JSX为开发人员提供了一个抽象层,使他们可以专注于描述UI应该是什么样子,而不是如何创建和操作DOM元素。
4. JSX是用什么工具解析的?
JSX通常使用Babel这样的JavaScript编译器进行解析。Babel是一个广泛使用的JavaScript编译器,它可以将ES6+代码转换为向后兼容的JavaScript版本,以便在当前和旧版本的浏览器中使用。对于JSX,Babel使用了一个叫做@babel/preset-react
的预设来解析和转换JSX代码。
@babel/preset-react
@babel/preset-react
是一个Babel预设(preset),它包含了多个与React相关的插件的集合,用于转换JSX语法和React的特定功能。这个预设通常包括:
@babel/plugin-syntax-jsx
:允许Babel解析JSX语法。@babel/plugin-transform-react-jsx
:将JSX元素转换为React函数调用(通常是React.createElement
或新的jsx
/jsxs
运行时函数)。- 可能还包括其他插件,如
@babel/plugin-transform-react-display-name
,用于增强React组件的调试信息。
安装这个预设后,你只需要在Babel的配置文件(如.babelrc
或babel.config.js
)中添加"presets": ["@babel/preset-react"]
,Babel就会自动应用这个预设中包含的所有插件。
5. JSX是如何解析的?
JSX的解析过程大致如下:
- 词法分析:JSX代码首先被分解成一系列的标记,这些标记代表了代码中的不同部分,如标签名、属性名和属性值等。
- 语法分析:接下来,这些标记被组织成一棵抽象语法树(AST),这棵树表示了JSX代码的结构。
- 转换 :在AST上执行一系列的转换操作,将JSX代码转换为普通的JavaScript代码。这包括将JSX标签转换为
React.createElement
函数调用等。 - 生成代码:最后,从转换后的AST生成可执行的JavaScript代码。
6. JSX解析最终是什么样的?
jsx代码
js
<div>
<h1>hello,world</h1>
<span>React JSX</span>
</div>
在使用新的JSX Transform后,会被转换为:
js
_jsxs("div",
{
children: [
_jsx("h1", { children: "hello,world" }),
_jsx("span", { children:"React JSX"}),
]
});
老版本JSX会被转换为:
js
React.createElement( "div", null,
React.createElement("h1", null,"hello,world"),
React.createElement("span", null, "React JSX")
);
7.之前为什么需要引入React?
在早期的React版本中,当你使用JSX语法编写组件时,Babel(一个广泛使用的JavaScript编译器)会将JSX转换为常规的JavaScript。这个转换过程中,会生成React.createElement()的调用,而这就需要React对象。因此,你需要在每个使用JSX的文件中显式地引入React。
现在为什么不需要了?
- JSX Transform: 在React 17及更高版本中,React团队引入了一个新的JSX转换方式,它不再需要在每个文件中引入React。这个新的转换方式允许Babel或TypeScript在不需要React对象的情况下将JSX转换为JavaScript。它通过自动导入必要的函数来实现这一点,从而减少了代码中的冗余。
- React的新版本和构建工具的发展: 随着React和与之相关的构建工具(如Babel和Webpack)的不断发展,这些工具能够更智能地处理依赖关系和优化代码。这意味着,即使你没有显式地引入React,这些工具也能确保React库在构建过程中被正确地包含和引用。
好处
- 减少样板代码 :不再需要在每个文件中都引入
React
,使代码更加简洁。 - 改进性能:减少了运行时需要处理的代码量,可能会带来轻微的性能提升。
- 更好的优化机会 :新的转换方式使得React库更容易进行树摇(tree-shaking)和其他优化,因为不再需要默认导出
React
对象。 - 未来兼容性 :为React的未来版本和新的功能提供了更好的兼容性,因为它们不再依赖于
React.createElement
。