03 React JSX转换
May 15, 2024About 1 min
- 实现 jsx 方法
- 实现打包流程
- 实现调试打包结果的环境
Babel · The compiler for next generation JavaScript
Babel 中试一试看看什么是 JSX 转换
<div class="test">123{test}234test<p>123</p><p>123</p></div>
React.createElement("div", {
class: "test"
}, "123", test, "234test", React.createElement("p", null, "123"), React.createElement("p", null, "123"));
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
_jsxs("div", {
class: "test",
children: ["123", test, "234test", _jsx("p", {
children: "123"
}),_jsx("p", {
children: "123"
})]
});
ReactElement 类型定义
reReact/packages/shared/ReactSymbols.ts 使用 Symbol 来实现
//检查环境是否支持 Symbol
const supportSymbol = typeof Symbol === 'function' && Symbol.for;
//创建一个 Symbol
export const REACT_ELEMENT_TYPE = supportSymbol
? Symbol.for('react.element')
: 0xeac7;
什么是 JSX
React.createElement() 方法
function createElement(tag, attrs, ...children) {
attrs = attrs || {}; // 返回一个JS对象,也就是虚拟Dom
return { tag, attrs, children, key: attrs.key || null, };
}
<div class="test">123{test}234test<p>123</p><p>123</p></div>
React.createElement("div", {
class: "test"
}, "123", test, "234test", React.createElement("p", null, "123"), React.createElement("p", null, "123"));
如何转换?
export const jsx = (type: ElementType, config: any, ...maybeChildren: any) => {
let key: Key = null;
const props: any = {};
let ref: Ref = null;
for (const prop in config) {
const val = config[prop];
if (prop === 'key') {
if (hasValidKey(config)) {
key = '' + val;
}
continue;
}
if (prop === 'ref' && val !== undefined) {
if (hasValidRef(config)) {
ref = val;
}
continue;
}
if ({}.hasOwnProperty.call(config, prop)) {
props[prop] = val;
}
}
const maybeChildrenLength = maybeChildren.length;
if (maybeChildrenLength) {
// 将多余参数作为children
if (maybeChildrenLength === 1) {
props.children = maybeChildren[0];
} else {
props.children = maybeChildren;
}
}
return ReactElement(type, key, ref, props);
};
各节点类型
- JSX
- React Element
- Fiber Node
- DOM Element