在 React 的世界里, JSX(JavaScript XML) 随处可见。它允许我们在 JavaScript 中写 HTML,甚至像写模板一样构建 UI,极大地提升了开发效率和代码可读性。
但你有没有想过:何为JSX ?为什么不能直接运行?它又是如何被转换编译的?Babel 又是干什么的?
一、何为JSX?
JSX(JavaScript XML) 是一种 JavaScript 的语法扩展,允许你以类似 HTML 的方式在 JavaScript 中编写结构化的 UI 元素。
示例:
const element = <h1>Hello World</h1>;
这段代码看起来像 HTML,但它其实是 JSX 语法。浏览器无法直接运行它,需要通过工具(如 Babel)将其转换为标准的 JavaScript 代码。
二、为什么不能直接运行 JSX?
因为 JSX 并不是原生 JavaScript 的语法。它属于 React 的开发工具链的一部分。浏览器不认识 <h1> 这样的标签,只能识别 JavaScript 的对象、函数等基本结构。
转换后的真实代码:
var element = /*#__PURE__*/React.createElement("h1", null, "Hello World");
这行代码才是浏览器可以执行的代码。它调用了 React.createElement 函数,创建了一个 React 元素对象。
三、JSX 是如何转换为 React.createElement 的?
来看下下面这段代码
function App() {
const [todos, setTodos] = useState([
{ id: 1, title: 'todo1' },
{ id: 2, title: 'todo2' },
{ id: 3, title: 'todo3' }
]);
const element = <h1 className='title'>Hello World</h1>;
const element2 = createElement('h1', { className: 'title', id: 'tit' }, 'Hello World');
return (
<>
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
<ul>
{todos.map(todo => (
createElement('li', { key: todo.id }, todo.title)
))}
</ul>
{element}
{element2}
</>
);
}
这段代码中使用了两种方式创建 React 元素:
- 使用 JSX 语法创建元素
- 使用
React.createElement手动创建元素
1. JSX 方式:
const element = <h1 className='title'>Hello World</h1>;
这是标准的 JSX 写法。它在开发时非常直观,但在运行前必须被 Babel 转换为 React.createElement 调用。
2. createElement 方式:
const element2 = createElement('h1', { className: 'title', id: 'tit' }, 'Hello World');
这是 JSX 被转换后的等价写法。React.createElement 接收三个参数:
type:元素类型(字符串'h1',或组件MyComponent)props:属性对象(如className,id)children:子元素(可以是字符串、数字、其他元素)
四、JSX 与 React.createElement 的关系
JSX 是
React.createElement的语法糖。
也就是说,JSX 最终都会被 Babel 转换为 React.createElement 的调用。
示例:
<li key={todo.id}>{todo.title}</li>
会被 Babel 转换为:
React.createElement('li', { key: todo.id }, todo.title);
这也是为什么你可以在一个 React 项目中同时使用 JSX 和 React.createElement,它们本质上是等价的。
五、JSX 的特性与注意事项
✅ JSX 的优点:
- 结构清晰:UI 层代码更直观。
- 嵌套自然:像写 HTML 一样嵌套组件。
- 开发效率高:配合 React DevTools 可视化调试方便。
⚠️ JSX 的注意事项:
1. 必须引入 React(逗你呢!Reat 17以上的版本就没这说法了)
在React 17 之前,即使你没有显式使用 React,会报错React is not defined,所以你必须在文件顶部写:
import React from 'react';
🚀 React 17 的新特性:运行时自动引入 React
从 React 17 开始,Facebook 团队与 Babel 团队合作,推出了一项新特性:
新的 JSX 转换方式(New JSX Transform)
它不再需要你手动 import React from 'react',因为:
- JSX 不再转换为
React.createElement(...)。 - 而是转换为一个自动引入的、内部的
jsx函数。
2. 不能返回多个根元素
一个组件的 return 中只能有一个根元素,可以使用 <>...</> 或 <div>...</div> 包裹:
return (
<>
<h1>Hello</h1>
<p>World</p>
</>
);
3. 不能使用 class 属性
在 JSX 中,class 是 JavaScript 的保留字,所以要写成 className:
<h1 className="title">Hello</h1>
4. 不能使用 for 属性
<label for="input"> 是 HTML 的写法,但在 JSX 中要写成 htmlFor:
<label htmlFor="input">用户名</label>
🤓 为什么?
因为for也是 JavaScript 的保留关键字,用于for循环。所以 React 选择了htmlFor来代替 HTML 中的for属性。
六、JSX 是如何被编译的?Babel 的作用
1. 安装 Babel 工具链
bun add --dev @babel/cli @babel/core @babel/preset-env @babel/preset-react
@babel/cli:命令行工具,用于手动编译文件。@babel/core:Babel 的核心引擎。@babel/preset-env:将 ES6+ 转换为 ES5。@babel/preset-react:支持 JSX 语法。
2. 创建 .babelrc 配置文件
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
3. 使用 Babel 编译 JSX 文件
./node_modules/.bin/babel 1.jsx -o 2.js
这个命令会将 1.jsx 中的 JSX 和 ES6+ 语法转换为浏览器可以运行的 ES5 代码。
七、为什么需要 Babel?
Make JavaScript Great Again!
让js再次伟大!!! 哈哈哈哈
Babel 的核心功能:
- 将 ES6+ 语法 转换为 ES5,兼容旧浏览器。
- 将 JSX 转换为
React.createElement调用。 - 支持 TypeScript、Flow、JSX 等多种扩展语法。
- 提供插件机制,高度可扩展。
举个例子:
你写:
const greet = (name) => `Hello, ${name}`;
Babel 会帮你转成:
var greet = function greet(name) {
return 'Hello, ' + name;
};
这样即使你的浏览器不支持箭头函数,也能正常运行。
八、开发依赖 vs 生产依赖:devDependencies 和 dependencies 有什么区别?
在 package.json 中,我们通常会看到两个依赖项分类:
{
"dependencies": {
"react": "^19.1.0"
},
"devDependencies": {
"@babel/cli": "^7.28.0",
"@babel/core": "^7.28.0"
}
}
解释
| 类型 | 英文 | 中文 | 作用 | 举例 |
|---|---|---|---|---|
| 生产依赖 | dependencies | 上线时也需要的依赖 | 应用正常运行所必须 | react, react-dom, lodash |
| 开发依赖 | devDependencies | 开发时才需要的依赖 | 构建、编译、测试等工具 | babel, eslint, webpack |
理解
dependencies就像你家里的家具:没有它们,家就住不了。devDependencies就像你装修时用的工具:装修完就收起来了,不需要带进房间。
为什么上线不用 Babel?
因为 Babel 只在开发阶段使用。上线时,代码已经被编译成标准的 JavaScript,不再需要 Babel。
JSX 让 React 的开发体验更直观、更高效,而 Babel 是让这一切成为可能的“幕后英雄”。理解 JSX 和 Babel 的关系,是掌握 React 开发的关键一步。