# JSX 最后会变成什么
- SX 元素节点 会被 bable 编译成 React Element 形式。那么,我们首先来看一下 React.createElement 的用法。
- React.createElement 处理后会 React element 对象的每一个子节点都会形成一个与之对应的 fiber 对象,然后通过 sibling、return、child 将每一个 fiber 对象联系起来。
fiber 对应关系
- child: 一个由父级 fiber 指向子级 fiber 的指针。
- return:一个子级 fiber 指向父级 fiber 的指针。
- sibling: 一个 fiber 指向下一个兄弟 fiber 的指针。
# 可控性 render
- 返回的 children 虽然是一个数组,但是数组里面的数据类型却是不确定的,有对象类型( 如 ReactElement ) ,有数组类型(如 map 遍历返回的子节点),还有字符串类型(如文本);
- 无法对 render 后的 React element 元素进行可控性操作。
- 将上述 children 扁平化处理,将数组类型的子节点打开 ;
- 干掉 children 中文本类型节点;
- 向 children 最后插入 say goodbye 元素;
- 克隆新的元素节点并渲染。
# Babel 解析 JSX 流程
1 @babel/plugin-syntax-jsx 和 @babel/plugin-transform-react-jsx
Automatic Runtime 模式的时候不用引入 React createElement **因为 plugin-syntax-jsx 已经向文件中提前注入了 _jsxRuntime api。不过这种模式下需要我们在 .babelrc 设置 runtime: automatic 。 **
bable 解析 jsx const fs = require('fs') const babel = require("@babel/core")
/_ 第一步:模拟读取文件内容。 _/
const fs = require("fs");
const babel = require("@babel/core");
/* 第一步:模拟读取文件内容。 */
fs.readFile("./element.js", (e, data) => {
const code = data.toString("utf-8");
/* 第二步:转换 jsx 文件 */
const result = babel.transformSync(code, {
plugins: ["@babel/plugin-transform-react-jsx"],
});
/* 第三步:模拟重新写入内容。 */
fs.writeFile("./element.js", result.code, function () {});
});
处理后
import React from "react";
function TestComponent() {
return /*#__PURE__*/ React.createElement("p", null, " hello,React ");
}
function Index() {
return /*#__PURE__*/ React.createElement(
"div",
null,
/*#__PURE__*/ React.createElement(
"span",
null,
"\u6A21\u62DF babel \u5904\u7406 jsx \u6D41\u7A0B\u3002"
),
/*#__PURE__*/ React.createElement(TestComponent, null)
);
}
export default Index;