JSX 本质
JSX 是什么,如何被编译,最终变成什么
问题
JSX 的本质是什么?它是如何工作的?
解答
JSX 是 JavaScript 的语法扩展,它会被 Babel 编译成 React.createElement() 函数调用,最终返回一个描述 UI 的普通 JavaScript 对象(React Element)。
JSX 编译过程
// 你写的 JSX
const element = (
<div className="container">
<h1>Hello</h1>
<p>World</p>
</div>
);
// Babel 编译后(React 17 之前)
const element = React.createElement(
'div',
{ className: 'container' },
React.createElement('h1', null, 'Hello'),
React.createElement('p', null, 'World')
);
// Babel 编译后(React 17+ 新转换)
import { jsx as _jsx, jsxs as _jsxs } from 'react/jsx-runtime';
const element = _jsxs('div', {
className: 'container',
children: [
_jsx('h1', { children: 'Hello' }),
_jsx('p', { children: 'World' })
]
});
React.createElement 返回值
// React.createElement 返回的对象结构
const element = {
$$typeof: Symbol(react.element), // 标识这是 React 元素
type: 'div', // 元素类型
key: null, // 列表渲染的 key
ref: null, // ref 引用
props: { // 属性
className: 'container',
children: [
{ $$typeof: Symbol(react.element), type: 'h1', props: { children: 'Hello' } },
{ $$typeof: Symbol(react.element), type: 'p', props: { children: 'World' } }
]
}
};
手写简易 createElement
function createElement(type, props, ...children) {
return {
$$typeof: Symbol.for('react.element'),
type,
key: props?.key || null,
ref: props?.ref || null,
props: {
...props,
children: children.length === 1 ? children[0] : children
}
};
}
// 使用
const element = createElement(
'div',
{ className: 'box' },
createElement('span', null, 'text')
);
console.log(element);
// {
// $$typeof: Symbol(react.element),
// type: 'div',
// key: null,
// ref: null,
// props: { className: 'box', children: { type: 'span', ... } }
// }
组件类型的处理
// 函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// JSX 使用组件
const element = <Welcome name="Sara" />;
// 编译后,type 是函数引用
const element = React.createElement(Welcome, { name: 'Sara' });
// 返回的对象
{
$$typeof: Symbol(react.element),
type: Welcome, // 函数引用,不是字符串
props: { name: 'Sara' }
}
关键点
- JSX 是语法糖,不是模板语言,最终编译成函数调用
React.createElement(type, props, ...children)返回普通 JS 对象- 原生标签的 type 是字符串(如
'div'),组件的 type 是函数/类引用 $$typeof用于防止 XSS 攻击,JSON 无法表示 Symbol- React 17+ 使用新的 JSX 转换,不再需要手动引入 React
目录