官方模拟版
2023年06月11日
一、准备
@babel/cli
@babel/core
@babel/plugin-transform-react-jsx
二、编译
2.1 package.json
pnpm init
生成 package.json
, 配置Babel
编译运行命令为: babel App.jsx -o App.js --watch
{
"name": "jsx",
"type": "module",
"scripts": {
"jsx": "babel App.jsx -o App.js --watch"
},
"devDependencies": {
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.3",
"@babel/plugin-transform-react-jsx": "^7.22.15"
}
}
2.2 babel.config.js
通过 @babel/plugin-transform-react-jsx
插件进行编译解析 .jsx
文件, 其中 runtime
有两种模式:
-
classic
: 编译解析为React.js 17.0
之前语法 -
automatic
: 编译解析为React.js 17.0
之后语法
export default {
presets: [
[
'@babel/env',
{
"modules": false
}
]
],
plugins: [['@babel/plugin-transform-react-jsx', { runtime: 'classic' }]]
};
2.3 App.jsx
function App() {
return <div className="page-app">Hello World</div>;
}
export default App;
三、react/jsx.js ReactElement
// const supportSymbol = typeof Symbol === 'function' && Symbol.for;
// export const REACT_ELEMENT_TYPE = supportSymbol
// ? Symbol.for('react.element')
// : 0xeac7;
import { REACT_ELEMENT_TYPE } from '../shared/ReactSymbols.js';
const ReactElement = function (type, key, ref, props) {
const element = {
$$typeof: REACT_ELEMENT_TYPE,
type,
key,
ref,
props
};
return element;
};
四、react/jsx.js jsx()
export function jsx(type, config, ...maybeChildren) {
let key = null;
const props = {};
let ref = null;
for (const prop in config) {
const val = config[prop];
if (prop === 'key') {
if (val !== undefined) {
key = '' + val;
}
continue;
}
if (prop === 'ref') {
if (val !== undefined) {
ref = val;
}
continue;
}
if ({}.hasOwnProperty.call(config, prop)) {
props[prop] = val;
}
}
const maybeChildrenLength = maybeChildren.length;
if (maybeChildrenLength) {
if (maybeChildrenLength === 1) {
props.children = maybeChildren[0];
} else {
props.children = maybeChildren;
}
}
return ReactElement(type, key, ref, props);
}
五、createElement()
六、react/index.js
import { jsx } from './jsx.js';
export default {
version: '0.0.0',
createElement: jsx
};