跳到主要内容

官方模拟版

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
};